mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
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:
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
44
drivers/media/platform/rockchip/isp/isp_external.h
Normal file
44
drivers/media/platform/rockchip/isp/isp_external.h
Normal 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
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user