media: rockchip: isp: vicap direct to isp3.0

Change-Id: I12ca0c29e44956bee806a020a4a1821daaa019e2
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2021-07-02 15:04:19 +08:00
committed by Tao Huang
parent 8b9c3e10f2
commit b5157fe547
6 changed files with 216 additions and 6 deletions

View File

@@ -12,6 +12,7 @@
#include <media/v4l2-subdev.h>
#include <media/videobuf2-dma-contig.h>
#include "dev.h"
#include "isp_external.h"
#include "regs.h"
static void get_remote_mipi_sensor(struct rkisp_device *dev,
@@ -436,6 +437,10 @@ int rkisp_csi_config_patch(struct rkisp_device *dev)
} else {
if (dev->isp_inp & INP_CIF) {
struct rkmodule_hdr_cfg hdr_cfg;
struct rkisp_vicap_mode mode = {
.name = dev->name,
.is_rdbk = true,
};
get_remote_mipi_sensor(dev, &mipi_sensor, MEDIA_ENT_F_PROC_VIDEO_COMPOSER);
dev->hdr.op_mode = HDR_NORMAL;
@@ -454,6 +459,30 @@ int rkisp_csi_config_patch(struct rkisp_device *dev)
/* normal read back mode */
if (dev->hdr.op_mode == HDR_NORMAL)
dev->hdr.op_mode = HDR_RDBK_FRAME1;
if (dev->isp_inp == INP_CIF && dev->hw_dev->is_single)
mode.is_rdbk = false;
v4l2_subdev_call(mipi_sensor, core, ioctl,
RKISP_VICAP_CMD_MODE, &mode);
/* vicap direct to isp */
if (dev->isp_ver == ISP_V30 && dev->hw_dev->is_single) {
switch (dev->hdr.op_mode) {
case HDR_RDBK_FRAME3:
dev->hdr.op_mode = HDR_LINEX3_DDR;
break;
case HDR_RDBK_FRAME2:
dev->hdr.op_mode = HDR_LINEX2_DDR;
break;
default:
dev->hdr.op_mode = HDR_NORMAL;
}
if (dev->hdr.op_mode != HDR_NORMAL && mipi_sensor) {
int cnt = RKISP_VICAP_BUF_CNT;
v4l2_subdev_call(mipi_sensor, core, ioctl,
RKISP_VICAP_CMD_INIT_BUF, &cnt);
}
}
} else {
switch (dev->isp_inp & 0x7) {
case INP_RAWRD2 | INP_RAWRD0:
@@ -467,15 +496,26 @@ int rkisp_csi_config_patch(struct rkisp_device *dev)
}
}
if (dev->hdr.op_mode == HDR_RDBK_FRAME2)
val = SW_HDRMGE_EN | SW_HDRMGE_MODE_FRAMEX2;
else if (dev->hdr.op_mode == HDR_RDBK_FRAME3)
val = SW_HDRMGE_EN | SW_HDRMGE_MODE_FRAMEX3;
if (!dev->hw_dev->is_mi_update)
rkisp_write(dev, CSI2RX_CTRL0,
SW_IBUF_OP_MODE(dev->hdr.op_mode), true);
/* hdr merge */
switch (dev->hdr.op_mode) {
case HDR_RDBK_FRAME2:
case HDR_FRAMEX2_DDR:
case HDR_LINEX2_DDR:
case HDR_LINEX2_NO_DDR:
val = SW_HDRMGE_EN | SW_HDRMGE_MODE_FRAMEX2;
break;
case HDR_RDBK_FRAME3:
case HDR_FRAMEX3_DDR:
case HDR_LINEX3_DDR:
val = SW_HDRMGE_EN | SW_HDRMGE_MODE_FRAMEX3;
break;
default:
val = 0;
}
if (is_feature_on) {
if ((ISP2X_MODULE_HDRMGE & ~iq_feature) && (val & SW_HDRMGE_EN)) {
v4l2_err(&dev->v4l2_dev, "hdrmge is not supported\n");

View File

@@ -126,7 +126,7 @@ static int __isp_pipeline_prepare(struct rkisp_pipeline *p,
p->num_subdevs = 0;
memset(p->subdevs, 0, sizeof(p->subdevs));
if (!(dev->isp_inp & (INP_CSI | INP_DVP | INP_LVDS)))
if (!(dev->isp_inp & (INP_CSI | INP_DVP | INP_LVDS | INP_CIF)))
return 0;
while (1) {
@@ -259,8 +259,13 @@ static int rkisp_pipeline_open(struct rkisp_pipeline *p,
static int rkisp_pipeline_close(struct rkisp_pipeline *p)
{
struct rkisp_device *dev = container_of(p, struct rkisp_device, pipe);
atomic_dec(&p->power_cnt);
if (dev->isp_ver == ISP_V30 && !atomic_read(&p->power_cnt))
rkisp_rx_buf_pool_free(dev);
return 0;
}

View File

@@ -45,6 +45,7 @@
#include "isp_stats.h"
#include "isp_mipi_luma.h"
#include "procfs.h"
#include "isp_external.h"
#define DRIVER_NAME "rkisp"
#define ISP_VDEV_NAME DRIVER_NAME "_ispdev"
@@ -227,5 +228,7 @@ struct rkisp_device {
int rdbk_cnt_x3;
u32 rd_mode;
u8 filt_state[RDBK_F_MAX];
struct rkisp_rx_buf_pool pv_pool[RKISP_RX_BUF_POOL_MAX];
};
#endif

View File

@@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2021 Fuzhou Rockchip Electronics Co., Ltd. */
#ifndef _RKISP_EXTERNAL_H
#define _RKISP_EXTERNAL_H
#define RKISP_VICAP_CMD_MODE \
_IOW('V', BASE_VIDIOC_PRIVATE + 0, struct rkisp_vicap_mode)
#define RKISP_VICAP_CMD_INIT_BUF \
_IOW('V', BASE_VIDIOC_PRIVATE + 1, int)
#define RKISP_VICAP_BUF_CNT 1
#define RKISP_RX_BUF_POOL_MAX (RKISP_VICAP_BUF_CNT * 3)
struct rkisp_vicap_mode {
char *name;
bool is_rdbk;
};
enum rx_buf_type {
BUF_SHORT,
BUF_MIDDLE,
BUF_LONG,
};
struct rkisp_rx_buf_pool {
struct rkisp_rx_buf *dbufs;
void *mem_priv;
dma_addr_t dma;
void *vaddr;
};
struct rkisp_rx_buf {
struct list_head list;
struct dma_buf *dbuf;
enum rx_buf_type type;
u64 timestamp;
u32 sequence;
bool is_init;
};
#endif

View File

@@ -49,6 +49,7 @@
#include <media/media-entity.h>
#include "common.h"
#include "isp_external.h"
#include "regs.h"
#include "rkisp_tb_helper.h"
@@ -2324,6 +2325,107 @@ static int rkisp_isp_sd_s_stream(struct v4l2_subdev *sd, int on)
return 0;
}
void rkisp_rx_buf_pool_free(struct rkisp_device *dev)
{
const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops;
struct rkisp_rx_buf_pool *pool;
int i;
for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) {
pool = &dev->pv_pool[i];
if (!pool->dbufs)
break;
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;
}
}
static int rkisp_rx_buf_pool_init(struct rkisp_device *dev,
struct rkisp_rx_buf *dbufs)
{
const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops;
struct rkisp_stream *stream;
struct rkisp_rx_buf_pool *pool;
struct sg_table *sg_tbl;
int i, ret;
void *mem;
for (i = 0; i < RKISP_RX_BUF_POOL_MAX; i++) {
pool = &dev->pv_pool[i];
if (!pool->dbufs)
break;
}
pool->dbufs = dbufs;
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
"%s type:0x%x dbufs[%d]:%p", __func__, dbufs->type, i, dbufs);
mem = g_ops->attach_dmabuf(dev->hw_dev->dev, dbufs->dbuf,
dbufs->dbuf->size, DMA_BIDIRECTIONAL);
if (IS_ERR(mem)) {
ret = PTR_ERR(mem);
goto err;
}
pool->mem_priv = mem;
ret = g_ops->map_dmabuf(mem);
if (ret)
goto err;
if (dev->hw_dev->is_dma_sg_ops) {
sg_tbl = (struct sg_table *)g_ops->cookie(mem);
pool->dma = sg_dma_address(sg_tbl->sgl);
} else {
pool->dma = *((dma_addr_t *)g_ops->cookie(mem));
}
get_dma_buf(dbufs->dbuf);
pool->vaddr = g_ops->vaddr(mem);
dbufs->is_init = true;
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];
}
stream->ops->config_mi(stream);
rkisp_write(dev, stream->config->mi.y_base_ad_init, pool->dma, false);
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
"%s dma:0x%x vaddr:%p", __func__, (u32)pool->dma, pool->vaddr);
return 0;
err:
rkisp_rx_buf_pool_free(dev);
return ret;
}
static int rkisp_sd_s_rx_buffer(struct v4l2_subdev *sd,
void *buf, unsigned int *size)
{
struct rkisp_device *dev = sd_to_isp_dev(sd);
struct rkisp_rx_buf *dbufs;
int ret = 0;
if (!buf)
return -EINVAL;
dbufs = buf;
if (!dbufs->is_init)
ret = rkisp_rx_buf_pool_init(dev, dbufs);
/* TODO qbuf/debuf for more buffer */
return ret;
}
static int rkisp_isp_sd_s_power(struct v4l2_subdev *sd, int on)
{
struct rkisp_device *isp_dev = sd_to_isp_dev(sd);
@@ -2463,6 +2565,19 @@ static int rkisp_subdev_link_setup(struct media_entity *entity,
else
dev->dmarx_dev.trigger = T_AUTO;
if (dev->isp_inp & INP_CIF) {
struct v4l2_subdev *remote = get_remote_sensor(sd);
struct rkisp_vicap_mode mode;
mode.name = dev->name;
mode.is_rdbk = !!(dev->isp_inp & rawrd);
/* read back mode only */
if (dev->isp_ver < ISP_V30 || !dev->hw_dev->is_single)
mode.is_rdbk = true;
v4l2_subdev_call(remote, core, ioctl,
RKISP_VICAP_CMD_MODE, &mode);
}
v4l2_dbg(1, rkisp_debug, &dev->v4l2_dev,
"isp input:0x%x\n", dev->isp_inp);
return 0;
@@ -2724,6 +2839,7 @@ static const struct media_entity_operations rkisp_isp_sd_media_ops = {
static const struct v4l2_subdev_video_ops rkisp_isp_sd_video_ops = {
.s_stream = rkisp_isp_sd_s_stream,
.s_rx_buffer = rkisp_sd_s_rx_buffer,
};
static const struct v4l2_subdev_core_ops rkisp_isp_core_ops = {

View File

@@ -172,6 +172,8 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo
int rkisp_rdbk_trigger_event(struct rkisp_device *dev, u32 cmd, void *arg);
void rkisp_rx_buf_pool_free(struct rkisp_device *dev);
static inline
struct ispsd_out_fmt *rkisp_get_ispsd_out_fmt(struct rkisp_isp_subdev *isp_sdev)
{