media: rockchip: vicap support rockit

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: I4748ecdf0909c8af71a311f43022b796c531d5be
This commit is contained in:
Zefa Chen
2022-08-30 11:18:15 +08:00
parent 89611a83d2
commit fce76cf947
5 changed files with 758 additions and 6 deletions

View File

@@ -9,4 +9,5 @@ video_rkcif-objs += dev.o \
procfs.o \
cif-scale.o \
common.o \
cif-tools.o
cif-tools.o \
cif-rockit.o

View File

@@ -2604,6 +2604,285 @@ static int rkcif_assign_new_buffer_pingpong(struct rkcif_stream *stream,
return ret;
}
static void rkcif_assign_new_buffer_init_rockit(struct rkcif_stream *stream,
int channel_id)
{
struct rkcif_device *dev = stream->cifdev;
struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
u32 frm0_addr_y, frm0_addr_uv;
u32 frm1_addr_y, frm1_addr_uv;
unsigned long flags;
struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
struct csi_channel_info *channel = &dev->channels[channel_id];
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) {
frm0_addr_y = get_reg_index_of_frm0_y_addr(channel_id);
frm0_addr_uv = get_reg_index_of_frm0_uv_addr(channel_id);
frm1_addr_y = get_reg_index_of_frm1_y_addr(channel_id);
frm1_addr_uv = get_reg_index_of_frm1_uv_addr(channel_id);
} else {
frm0_addr_y = get_dvp_reg_index_of_frm0_y_addr(channel_id);
frm0_addr_uv = get_dvp_reg_index_of_frm0_uv_addr(channel_id);
frm1_addr_y = get_dvp_reg_index_of_frm1_y_addr(channel_id);
frm1_addr_uv = get_dvp_reg_index_of_frm1_uv_addr(channel_id);
}
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!stream->curr_buf_rockit) {
if (!list_empty(&stream->rockit_buf_head)) {
stream->curr_buf_rockit = list_first_entry(&stream->rockit_buf_head,
struct rkcif_buffer,
queue);
list_del(&stream->curr_buf_rockit->queue);
}
}
if (stream->curr_buf_rockit) {
rkcif_write_register(dev, frm0_addr_y,
stream->curr_buf_rockit->buff_addr[RKCIF_PLANE_Y]);
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm0_addr_uv,
stream->curr_buf_rockit->buff_addr[RKCIF_PLANE_CBCR]);
} else {
if (dummy_buf->vaddr) {
rkcif_write_register(dev, frm0_addr_y, dummy_buf->dma_addr);
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm0_addr_uv, dummy_buf->dma_addr);
} else {
if (stream->lack_buf_cnt < 2)
stream->lack_buf_cnt++;
}
}
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
stream->next_buf_rockit = stream->curr_buf_rockit;
if (stream->next_buf_rockit) {
rkcif_write_register(dev, frm1_addr_y,
stream->next_buf_rockit->buff_addr[RKCIF_PLANE_Y] + (channel->virtual_width / 2));
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm1_addr_uv,
stream->next_buf_rockit->buff_addr[RKCIF_PLANE_CBCR] + (channel->virtual_width / 2));
}
} else {
if (!stream->next_buf_rockit) {
if (!list_empty(&stream->rockit_buf_head)) {
stream->next_buf_rockit = list_first_entry(&stream->rockit_buf_head,
struct rkcif_buffer, queue);
list_del(&stream->next_buf_rockit->queue);
}
}
if (stream->next_buf_rockit) {
rkcif_write_register(dev, frm1_addr_y,
stream->next_buf_rockit->buff_addr[RKCIF_PLANE_Y]);
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm1_addr_uv,
stream->next_buf_rockit->buff_addr[RKCIF_PLANE_CBCR]);
} else {
if (dummy_buf->vaddr) {
rkcif_write_register(dev, frm1_addr_y, dummy_buf->dma_addr);
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm1_addr_uv, dummy_buf->dma_addr);
} else {
if (stream->curr_buf_rockit) {
stream->next_buf_rockit = stream->curr_buf_rockit;
rkcif_write_register(dev, frm1_addr_y,
stream->next_buf_rockit->buff_addr[RKCIF_PLANE_Y]);
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm1_addr_uv,
stream->next_buf_rockit->buff_addr[RKCIF_PLANE_CBCR]);
}
if (stream->lack_buf_cnt < 2)
stream->lack_buf_cnt++;
}
}
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
stream->is_dvp_yuv_addr_init = true;
/* for BT.656/BT.1120 multi channels function,
* yuv addr of unused channel must be set
*/
if (mbus_cfg->type == V4L2_MBUS_BT656) {
int ch_id;
for (ch_id = 0; ch_id < RKCIF_MAX_STREAM_DVP; ch_id++) {
if (dev->stream[ch_id].is_dvp_yuv_addr_init)
continue;
if (dummy_buf->dma_addr) {
rkcif_write_register(dev,
get_dvp_reg_index_of_frm0_y_addr(ch_id),
dummy_buf->dma_addr);
rkcif_write_register(dev,
get_dvp_reg_index_of_frm0_uv_addr(ch_id),
dummy_buf->dma_addr);
rkcif_write_register(dev,
get_dvp_reg_index_of_frm1_y_addr(ch_id),
dummy_buf->dma_addr);
rkcif_write_register(dev,
get_dvp_reg_index_of_frm1_uv_addr(ch_id),
dummy_buf->dma_addr);
}
}
}
stream->buf_owner = RKCIF_DMAEN_BY_ROCKIT;
}
static int rkcif_assign_new_buffer_update_rockit(struct rkcif_stream *stream,
int channel_id)
{
struct rkcif_device *dev = stream->cifdev;
struct rkcif_dummy_buffer *dummy_buf = &dev->hw_dev->dummy_buf;
struct v4l2_mbus_config *mbus_cfg = &dev->active_sensor->mbus;
struct rkcif_buffer *buffer = NULL;
u32 frm_addr_y, frm_addr_uv;
struct csi_channel_info *channel = &dev->channels[channel_id];
int ret = 0;
unsigned long flags;
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) {
frm_addr_y = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_reg_index_of_frm0_y_addr(channel_id) :
get_reg_index_of_frm1_y_addr(channel_id);
frm_addr_uv = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_reg_index_of_frm0_uv_addr(channel_id) :
get_reg_index_of_frm1_uv_addr(channel_id);
} else {
frm_addr_y = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_dvp_reg_index_of_frm0_y_addr(channel_id) :
get_dvp_reg_index_of_frm1_y_addr(channel_id);
frm_addr_uv = stream->frame_phase & CIF_CSI_FRAME0_READY ?
get_dvp_reg_index_of_frm0_uv_addr(channel_id) :
get_dvp_reg_index_of_frm1_uv_addr(channel_id);
}
spin_lock_irqsave(&stream->vbq_lock, flags);
if (!list_empty(&stream->rockit_buf_head)) {
if (!dummy_buf->vaddr &&
stream->curr_buf_rockit == stream->next_buf_rockit &&
stream->cif_fmt_in->field != V4L2_FIELD_INTERLACED)
ret = -EINVAL;
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
if (!stream->curr_buf_rockit)
ret = -EINVAL;
stream->curr_buf_rockit = list_first_entry(&stream->rockit_buf_head,
struct rkcif_buffer, queue);
if (stream->curr_buf_rockit) {
list_del(&stream->curr_buf_rockit->queue);
buffer = stream->curr_buf_rockit;
}
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (!stream->next_buf_rockit)
ret = -EINVAL;
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
if (stream->next_buf_rockit != stream->curr_buf_rockit) {
stream->next_buf_rockit = stream->curr_buf_rockit;
buffer = stream->next_buf_rockit;
} else {
buffer = NULL;
}
} else {
stream->next_buf_rockit = list_first_entry(&stream->rockit_buf_head,
struct rkcif_buffer, queue);
if (stream->next_buf_rockit) {
list_del(&stream->next_buf_rockit->queue);
buffer = stream->next_buf_rockit;
}
}
}
} else {
buffer = NULL;
if (dummy_buf->vaddr) {
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf_rockit = NULL;
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED) {
stream->next_buf_rockit = stream->curr_buf_rockit;
buffer = stream->next_buf_rockit;
} else {
stream->next_buf_rockit = NULL;
}
}
} else if (stream->curr_buf_rockit && stream->next_buf_rockit &&
stream->curr_buf_rockit != stream->next_buf_rockit) {
if (stream->frame_phase == CIF_CSI_FRAME0_READY) {
stream->curr_buf_rockit = stream->next_buf_rockit;
buffer = stream->next_buf_rockit;
} else if (stream->frame_phase == CIF_CSI_FRAME1_READY) {
stream->next_buf_rockit = stream->curr_buf_rockit;
buffer = stream->curr_buf_rockit;
}
if (stream->lack_buf_cnt < 2)
stream->lack_buf_cnt++;
} else {
if (stream->lack_buf_cnt < 2)
stream->lack_buf_cnt++;
}
}
stream->frame_phase_cache = stream->frame_phase;
if (buffer) {
if (stream->cif_fmt_in->field == V4L2_FIELD_INTERLACED &&
stream->frame_phase == CIF_CSI_FRAME1_READY) {
rkcif_write_register(dev, frm_addr_y,
buffer->buff_addr[RKCIF_PLANE_Y] + (channel->virtual_width / 2));
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm_addr_uv,
buffer->buff_addr[RKCIF_PLANE_CBCR] + (channel->virtual_width / 2));
} else {
rkcif_write_register(dev, frm_addr_y,
buffer->buff_addr[RKCIF_PLANE_Y]);
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm_addr_uv,
buffer->buff_addr[RKCIF_PLANE_CBCR]);
}
} else {
if (dummy_buf->vaddr) {
rkcif_write_register(dev, frm_addr_y, dummy_buf->dma_addr);
if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW)
rkcif_write_register(dev, frm_addr_uv, dummy_buf->dma_addr);
v4l2_info(&dev->v4l2_dev,
"not active buffer, use dummy buffer, %s stream[%d]\n",
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
stream->id);
} else {
ret = -EINVAL;
v4l2_dbg(3, rkcif_debug, &dev->v4l2_dev,
"not active buffer, lack_buf_cnt %d, stop capture, %s stream[%d]\n",
stream->lack_buf_cnt,
(mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY ||
mbus_cfg->type == V4L2_MBUS_CCP2) ? "mipi/lvds" : "dvp",
stream->id);
}
}
spin_unlock_irqrestore(&stream->vbq_lock, flags);
return ret;
}
static int rkcif_assign_new_buffer_pingpong_rockit(struct rkcif_stream *stream,
int init, int channel_id)
{
int ret = 0;
if (init)
rkcif_assign_new_buffer_init_rockit(stream, channel_id);
else
ret = rkcif_assign_new_buffer_update_rockit(stream, channel_id);
return ret;
}
static void rkcif_csi_get_vc_num(struct rkcif_device *dev,
unsigned int mbus_flags)
{
@@ -3241,6 +3520,10 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
rkcif_assign_new_buffer_pingpong_toisp(stream,
RKCIF_YUV_ADDR_STATE_INIT,
channel->id);
else if (mode == RKCIF_STREAM_MODE_ROCKIT)
rkcif_assign_new_buffer_pingpong_rockit(stream,
RKCIF_YUV_ADDR_STATE_INIT,
channel->id);
if (stream->lack_buf_cnt == 2)
stream->dma_en = 0;
@@ -3350,6 +3633,8 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode
stream->dma_en |= RKCIF_DMAEN_BY_ISP;
else if (dev->hdr.hdr_mode == HDR_X3 && (stream->id == 0 || stream->id == 1))
stream->dma_en |= RKCIF_DMAEN_BY_ISP;
} else if (mode == RKCIF_STREAM_MODE_ROCKIT) {
stream->dma_en |= RKCIF_DMAEN_BY_ROCKIT;
}
if (stream->cifdev->chip_id < CHIP_RK3588_CIF)
rkcif_csi_channel_set(stream, channel, mbus_type);
@@ -3370,6 +3655,8 @@ static int rkcif_csi_stream_start(struct rkcif_stream *stream, unsigned int mode
(stream->id == 0 || stream->id == 1) &&
(!stream->dma_en))
stream->to_en_dma = RKCIF_DMAEN_BY_ISP;
} else if (mode == RKCIF_STREAM_MODE_ROCKIT) {
stream->to_en_dma = RKCIF_DMAEN_BY_ROCKIT;
}
}
}
@@ -5540,6 +5827,7 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id)
INIT_LIST_HEAD(&stream->buf_head);
INIT_LIST_HEAD(&stream->rx_buf_head);
INIT_LIST_HEAD(&stream->rx_buf_head_vicap);
INIT_LIST_HEAD(&stream->rockit_buf_head);
spin_lock_init(&stream->vbq_lock);
spin_lock_init(&stream->fps_lock);
stream->state = RKCIF_STATE_READY;
@@ -7888,6 +8176,51 @@ static void rkcif_update_stream_toisp(struct rkcif_device *cif_dev,
mipi_id);
}
static void rkcif_update_stream_rockit(struct rkcif_device *cif_dev,
struct rkcif_stream *stream,
int mipi_id)
{
struct rkcif_buffer *active_buf = NULL;
unsigned long flags;
int ret = 0;
if (stream->frame_phase == (CIF_CSI_FRAME0_READY | CIF_CSI_FRAME1_READY)) {
v4l2_err(&cif_dev->v4l2_dev, "stream[%d], frm0/frm1 end simultaneously,frm id:%d\n",
stream->id, stream->frame_idx);
return;
}
if (!stream->is_line_wake_up) {
spin_lock_irqsave(&stream->fps_lock, flags);
if (stream->frame_phase & CIF_CSI_FRAME0_READY) {
if (stream->curr_buf_rockit)
active_buf = stream->curr_buf_rockit;
stream->fps_stats.frm0_timestamp = ktime_get_ns();
} else if (stream->frame_phase & CIF_CSI_FRAME1_READY) {
if (stream->next_buf_rockit)
active_buf = stream->next_buf_rockit;
stream->fps_stats.frm1_timestamp = ktime_get_ns();
}
spin_unlock_irqrestore(&stream->fps_lock, flags);
}
if (cif_dev->inf_id == RKCIF_MIPI_LVDS)
rkcif_deal_readout_time(stream);
ret = rkcif_assign_new_buffer_pingpong_rockit(stream,
RKCIF_YUV_ADDR_STATE_UPDATE,
mipi_id);
if (ret)
return;
if (active_buf) {
active_buf->vb.vb2_buf.timestamp = stream->readout.fs_timestamp;
active_buf->vb.sequence = stream->frame_idx - 1;
rkcif_rockit_buf_done(stream, active_buf);
}
}
static u32 rkcif_get_sof(struct rkcif_device *cif_dev)
{
u32 val = 0x0;
@@ -9221,7 +9554,10 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
rkcif_update_stream(cif_dev, stream, mipi_id);
} else if (stream->dma_en & RKCIF_DMAEN_BY_ISP) {
rkcif_update_stream_toisp(cif_dev, stream, mipi_id);
} else if (stream->dma_en & RKCIF_DMAEN_BY_ROCKIT) {
rkcif_update_stream_rockit(cif_dev, stream, mipi_id);
}
if (cif_dev->chip_id >= CHIP_RV1106_CIF)
rkcif_modify_frame_skip_config(stream);
if (stream->is_change_toisp) {

View File

@@ -0,0 +1,402 @@
// 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 <linux/of.h>
#include <linux/of_platform.h>
#include <soc/rockchip/rockchip_rockit.h>
#include "dev.h"
static struct rockit_rkcif_cfg *rockit_rkcif_cfg;
struct rkcif_rockit_buffer {
struct rkcif_buffer cif_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 rkcif_stream *rkcif_rockit_get_stream(struct rockit_rkcif_cfg *input_rockit_cfg)
{
struct rkcif_device *cif_dev = NULL;
struct rkcif_stream *stream = NULL;
u8 i;
if (!rockit_rkcif_cfg) {
pr_err("rockit_rkcif_cfg is null get stream failed\n");
return NULL;
}
if (!input_rockit_cfg) {
pr_err("input is null get stream failed\n");
return NULL;
}
for (i = 0; i < rockit_rkcif_cfg->cif_num; i++) {
if (!strcmp(rockit_rkcif_cfg->rkcif_dev_cfg[i].cif_name,
input_rockit_cfg->cur_name)) {
cif_dev = rockit_rkcif_cfg->rkcif_dev_cfg[i].cif_dev;
break;
}
}
if (cif_dev == NULL) {
pr_err("Can not find cif_dev!");
return NULL;
}
switch (input_rockit_cfg->nick_id) {
case 0:
stream = &cif_dev->stream[RKCIF_STREAM_MIPI_ID0];
break;
case 1:
stream = &cif_dev->stream[RKCIF_STREAM_MIPI_ID1];
break;
case 2:
stream = &cif_dev->stream[RKCIF_STREAM_MIPI_ID2];
break;
case 3:
stream = &cif_dev->stream[RKCIF_STREAM_MIPI_ID3];
break;
default:
stream = NULL;
break;
}
return stream;
}
int rkcif_rockit_buf_queue(struct rockit_rkcif_cfg *input_rockit_cfg)
{
struct rkcif_stream *stream = NULL;
struct rkcif_rockit_buffer *rkcif_buf = NULL;
struct rkcif_device *cif_dev = NULL;
const struct vb2_mem_ops *g_ops = NULL;
int i, ret, offset, dev_id;
struct rkcif_stream_cfg *stream_cfg = NULL;
void *mem = NULL;
struct sg_table *sg_tbl;
unsigned long lock_flags = 0;
stream = rkcif_rockit_get_stream(input_rockit_cfg);
if (stream == NULL) {
pr_err("the stream is NULL");
return -EINVAL;
}
cif_dev = stream->cifdev;
dev_id = cif_dev->csi_host_idx;
g_ops = cif_dev->hw_dev->mem_ops;
if (stream->id >= RKCIF_MAX_STREAM_MIPI)
return -EINVAL;
stream_cfg = &rockit_rkcif_cfg->rkcif_dev_cfg[dev_id].rkcif_stream_cfg[stream->id];
stream_cfg->node = input_rockit_cfg->node;
if (!input_rockit_cfg->buf)
return -EINVAL;
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;
}
}
if (input_rockit_cfg->is_alloc) {
for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) {
if (stream_cfg->buff_id[i] == 0) {
stream_cfg->rkcif_buff[i] =
kzalloc(sizeof(struct rkcif_rockit_buffer), GFP_KERNEL);
if (stream_cfg->rkcif_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;
rkcif_buf = stream_cfg->rkcif_buff[i];
rkcif_buf->mpi_buf = input_rockit_cfg->mpibuf;
mem = g_ops->attach_dmabuf(stream->cifdev->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");
rkcif_buf->mpi_mem = mem;
rkcif_buf->dmabuf = input_rockit_cfg->buf;
ret = g_ops->map_dmabuf(mem);
if (ret)
pr_err("the g_ops->map_dmabuf is error!\n");
if (stream->cifdev->hw_dev->is_dma_sg_ops) {
sg_tbl = (struct sg_table *)g_ops->cookie(mem);
rkcif_buf->buff_addr = sg_dma_address(sg_tbl->sgl);
} else {
rkcif_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++) {
rkcif_buf = stream_cfg->rkcif_buff[i];
if (stream_cfg->buff_id[i] == input_rockit_cfg->mpi_id)
break;
}
}
for (i = 0; i < stream->cif_fmt_out->mplanes; i++)
rkcif_buf->cif_buf.buff_addr[i] = rkcif_buf->buff_addr;
if (stream->cif_fmt_out->mplanes == 1) {
for (i = 0; i < stream->cif_fmt_out->cplanes - 1; i++) {
offset = stream->pixm.plane_fmt[i].bytesperline * stream->pixm.height;
rkcif_buf->cif_buf.buff_addr[i + 1] =
rkcif_buf->cif_buf.buff_addr[i] + offset;
}
}
v4l2_dbg(2, rkcif_debug, &cif_dev->v4l2_dev,
"stream:%d rockit_queue buf:0x%x\n",
stream->id, rkcif_buf->cif_buf.buff_addr[0]);
if (stream_cfg->is_discard)
return -EINVAL;
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
list_add_tail(&rkcif_buf->cif_buf.queue, &stream->rockit_buf_head);
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
return 0;
}
int rkcif_rockit_buf_done(struct rkcif_stream *stream, struct rkcif_buffer *buf)
{
struct rkcif_device *dev = stream->cifdev;
struct rkcif_rockit_buffer *rkcif_buf = NULL;
struct rkcif_stream_cfg *stream_cfg = NULL;
u32 dev_id = stream->cifdev->csi_host_idx;
if (!rockit_rkcif_cfg ||
!rockit_rkcif_cfg->rkcif_rockit_mpibuf_done ||
stream->id >= RKCIF_MAX_STREAM_MIPI)
return -EINVAL;
stream_cfg = &rockit_rkcif_cfg->rkcif_dev_cfg[dev_id].rkcif_stream_cfg[stream->id];
rkcif_buf =
container_of(buf, struct rkcif_rockit_buffer, cif_buf);
rockit_rkcif_cfg->mpibuf = rkcif_buf->mpi_buf;
rockit_rkcif_cfg->buf = rkcif_buf->dmabuf;
rockit_rkcif_cfg->frame.u64PTS = buf->vb.vb2_buf.timestamp;
rockit_rkcif_cfg->frame.u32TimeRef = buf->vb.sequence;
rockit_rkcif_cfg->frame.u32Height = stream->pixm.height;
rockit_rkcif_cfg->frame.u32Width = stream->pixm.width;
rockit_rkcif_cfg->frame.enPixelFormat = stream->pixm.pixelformat;
rockit_rkcif_cfg->frame.u32VirWidth = stream->pixm.width;
rockit_rkcif_cfg->frame.u32VirHeight = stream->pixm.height;
rockit_rkcif_cfg->cur_name = dev_name(dev->dev);
rockit_rkcif_cfg->node = stream_cfg->node;
if (list_empty(&stream->rockit_buf_head))
rockit_rkcif_cfg->is_empty = true;
else
rockit_rkcif_cfg->is_empty = false;
if (rockit_rkcif_cfg->rkcif_rockit_mpibuf_done)
rockit_rkcif_cfg->rkcif_rockit_mpibuf_done(rockit_rkcif_cfg);
return 0;
}
static int rkcif_rockit_buf_free(struct rkcif_stream *stream)
{
struct rkcif_rockit_buffer *rkcif_buf = NULL;
u32 i = 0, dev_id = stream->cifdev->csi_host_idx;
const struct vb2_mem_ops *g_ops = stream->cifdev->hw_dev->mem_ops;
struct rkcif_stream_cfg *stream_cfg = NULL;
if (!rockit_rkcif_cfg || stream->id >= RKCIF_MAX_STREAM_MIPI)
return -EINVAL;
stream_cfg = &rockit_rkcif_cfg->rkcif_dev_cfg[dev_id].rkcif_stream_cfg[stream->id];
stream_cfg->is_discard = false;
for (i = 0; i < ROCKIT_BUF_NUM_MAX; i++) {
if (stream_cfg->rkcif_buff[i]) {
rkcif_buf = (struct rkcif_rockit_buffer *)stream_cfg->rkcif_buff[i];
if (rkcif_buf->mpi_mem) {
g_ops->unmap_dmabuf(rkcif_buf->mpi_mem);
g_ops->detach_dmabuf(rkcif_buf->mpi_mem);
dma_buf_put(rkcif_buf->dmabuf);
}
kfree(stream_cfg->rkcif_buff[i]);
stream_cfg->rkcif_buff[i] = NULL;
stream_cfg->buff_id[i] = 0;
}
}
stream->curr_buf_rockit = NULL;
stream->next_buf_rockit = NULL;
INIT_LIST_HEAD(&stream->rockit_buf_head);
return 0;
}
int rkcif_rockit_pause_stream(struct rockit_rkcif_cfg *input_rockit_cfg)
{
struct rkcif_stream *stream = NULL;
stream = rkcif_rockit_get_stream(input_rockit_cfg);
if (stream == NULL) {
pr_err("the stream is NULL");
return -EINVAL;
}
rkcif_do_stop_stream(stream, RKCIF_STREAM_MODE_ROCKIT);
rkcif_rockit_buf_free(stream);
return 0;
}
EXPORT_SYMBOL(rkcif_rockit_pause_stream);
int rkcif_rockit_config_stream(struct rockit_rkcif_cfg *input_rockit_cfg,
int width, int height, int v4l2_fmt)
{
struct rkcif_stream *stream = NULL;
int ret;
stream = rkcif_rockit_get_stream(input_rockit_cfg);
if (stream == NULL) {
pr_err("the stream is NULL");
return -EINVAL;
}
stream->pixm.pixelformat = v4l2_fmt;
stream->pixm.width = width;
stream->pixm.height = height;
stream->pixm.plane_fmt[0].bytesperline = 0;
ret = rkcif_set_fmt(stream, &stream->pixm, false);
if (ret < 0) {
pr_err("stream id %d config failed\n", stream->id);
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(rkcif_rockit_config_stream);
int rkcif_rockit_resume_stream(struct rockit_rkcif_cfg *input_rockit_cfg)
{
struct rkcif_stream *stream = NULL;
int ret = 0;
stream = rkcif_rockit_get_stream(input_rockit_cfg);
if (stream == NULL) {
pr_err("the stream is NULL");
return -EINVAL;
}
ret = rkcif_do_start_stream(stream, RKCIF_STREAM_MODE_ROCKIT);
if (ret < 0) {
pr_err("stream id %d start failed\n", stream->id);
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(rkcif_rockit_resume_stream);
void rkcif_rockit_dev_init(struct rkcif_device *dev)
{
int i;
if (rockit_rkcif_cfg == NULL) {
rockit_rkcif_cfg = kzalloc(sizeof(struct rockit_rkcif_cfg), GFP_KERNEL);
if (rockit_rkcif_cfg == NULL)
return;
}
rockit_rkcif_cfg->cif_num = dev->hw_dev->dev_num;
for (i = 0; i < rockit_rkcif_cfg->cif_num; i++) {
if (dev->hw_dev->cif_dev[i]) {
rockit_rkcif_cfg->rkcif_dev_cfg[i].cif_name = dev_name(dev->hw_dev->cif_dev[i]->dev);
rockit_rkcif_cfg->rkcif_dev_cfg[i].cif_dev =
dev->hw_dev->cif_dev[i];
}
}
}
void rkcif_rockit_dev_deinit(void)
{
kfree(rockit_rkcif_cfg);
rockit_rkcif_cfg = NULL;
}
void *rkcif_rockit_function_register(void *function, int cmd)
{
if (rockit_rkcif_cfg == NULL) {
pr_err("rockit_cfg is null function register failed");
return NULL;
}
switch (cmd) {
case ROCKIT_BUF_QUE:
function = rkcif_rockit_buf_queue;
break;
case ROCKIT_MPIBUF_DONE:
rockit_rkcif_cfg->rkcif_rockit_mpibuf_done = function;
if (!rockit_rkcif_cfg->rkcif_rockit_mpibuf_done)
pr_err("get rkcif_rockit_mpibuf_done failed!");
break;
default:
break;
}
return function;
}
EXPORT_SYMBOL(rkcif_rockit_function_register);
int rkcif_rockit_get_cifdev(char **name)
{
int i = 0;
if (rockit_rkcif_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_rkcif_cfg->cif_num; i++)
name[i] = (char *)rockit_rkcif_cfg->rkcif_dev_cfg[i].cif_name;
if (name[0] == NULL)
return -EINVAL;
else
return 0;
}
EXPORT_SYMBOL(rkcif_rockit_get_cifdev);

View File

@@ -2023,6 +2023,8 @@ int rkcif_plat_uninit(struct rkcif_device *cif_dev)
}
rkcif_unregister_stream_vdevs(cif_dev, stream_num);
if (cif_dev->chip_id == CHIP_RV1106_CIF)
rkcif_rockit_dev_deinit();
return 0;
}
@@ -2137,6 +2139,8 @@ static int rkcif_plat_probe(struct platform_device *pdev)
dev_warn(dev, "dev:%s create proc failed\n", dev_name(dev));
rkcif_init_reset_monitor(cif_dev);
if (cif_dev->chip_id == CHIP_RV1106_CIF)
rkcif_rockit_dev_init(cif_dev);
pm_runtime_enable(&pdev->dev);
return 0;

View File

@@ -101,11 +101,12 @@ enum rkcif_workmode {
};
enum rkcif_stream_mode {
RKCIF_STREAM_MODE_NONE = 0x0,
RKCIF_STREAM_MODE_CAPTURE = 0x01,
RKCIF_STREAM_MODE_TOISP = 0x02,
RKCIF_STREAM_MODE_TOSCALE = 0x04,
RKCIF_STREAM_MODE_TOISP_RDBK = 0x08
RKCIF_STREAM_MODE_NONE = 0x0,
RKCIF_STREAM_MODE_CAPTURE = 0x01,
RKCIF_STREAM_MODE_TOISP = 0x02,
RKCIF_STREAM_MODE_TOSCALE = 0x04,
RKCIF_STREAM_MODE_TOISP_RDBK = 0x08,
RKCIF_STREAM_MODE_ROCKIT = 0x10
};
enum rkcif_yuvaddr_state {
@@ -445,6 +446,7 @@ enum rkcif_dma_en_mode {
RKCIF_DMAEN_BY_ISP = 0x2,
RKCIF_DMAEN_BY_VICAP_TO_ISP = 0x4,
RKCIF_DMAEN_BY_ISP_TO_VICAP = 0x8,
RKCIF_DMAEN_BY_ROCKIT = 0x10,
};
struct rkcif_skip_info {
@@ -484,6 +486,9 @@ struct rkcif_stream {
struct rkcif_buffer *next_buf;
struct rkcif_rx_buffer *curr_buf_toisp;
struct rkcif_rx_buffer *next_buf_toisp;
struct list_head rockit_buf_head;
struct rkcif_buffer *curr_buf_rockit;
struct rkcif_buffer *next_buf_rockit;
spinlock_t vbq_lock; /* vfd lock */
spinlock_t fps_lock;
@@ -909,5 +914,9 @@ int rkcif_clr_unready_dev(void);
const struct
cif_output_fmt *rkcif_find_output_fmt(struct rkcif_stream *stream, u32 pixelfmt);
/* Rockit */
int rkcif_rockit_buf_done(struct rkcif_stream *stream, struct rkcif_buffer *buf);
void rkcif_rockit_dev_init(struct rkcif_device *dev);
void rkcif_rockit_dev_deinit(void);
#endif