media: rockchip: isp: add luma stream for isp32

Change-Id: If20dfa24389b3df7f2ef0ad918cc649d9c560807
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2022-03-05 14:47:49 +08:00
committed by Tao Huang
parent 8dd3e56958
commit 8b0728ec75
5 changed files with 182 additions and 10 deletions

View File

@@ -442,7 +442,7 @@ int rkisp_stream_frame_start(struct rkisp_device *dev, u32 isp_mis)
rkisp_bridge_update_mi(dev, isp_mis);
for (i = 0; i < RKISP_MAX_STREAM; i++) {
if (i == RKISP_STREAM_VIR)
if (i == RKISP_STREAM_VIR || i == RKISP_STREAM_LUMA)
continue;
stream = &dev->cap_dev.stream[i];
if (stream->streaming &&
@@ -1032,6 +1032,13 @@ static int rkisp_set_fmt(struct rkisp_stream *stream,
pixm->width = t->out_fmt.width / 4;
pixm->height = t->out_fmt.height / 4;
}
} else if (stream->id == RKISP_STREAM_LUMA) {
struct v4l2_rect *out_crop = &dev->isp_sdev.out_crop;
bool bigmode = rkisp_params_check_bigmode(&dev->params_vdev);
u32 div = bigmode ? 32 : 16;
pixm->width = out_crop->width / div;
pixm->height = out_crop->height / div;
}
pixm->num_planes = fmt->mplanes;

View File

@@ -35,6 +35,8 @@
#ifndef _RKISP_PATH_VIDEO_H
#define _RKISP_PATH_VIDEO_H
#include <linux/interrupt.h>
#include "common.h"
#include "capture_v1x.h"
#include "capture_v2x.h"
@@ -47,6 +49,7 @@
#define BP_VDEV_NAME DRIVER_NAME "_bypasspath"
#define MPDS_VDEV_NAME DRIVER_NAME "_mainpath_4x4sampling"
#define BPDS_VDEV_NAME DRIVER_NAME "_bypasspath_4x4sampling"
#define LUMA_VDEV_NAME DRIVER_NAME "_lumapath"
#define VIR_VDEV_NAME DRIVER_NAME "_iqtool"
#define DMATX0_VDEV_NAME DRIVER_NAME "_rawwr0"
@@ -74,6 +77,7 @@ enum {
RKISP_STREAM_BP,
RKISP_STREAM_MPDS,
RKISP_STREAM_BPDS,
RKISP_STREAM_LUMA,
RKISP_STREAM_VIR,
RKISP_MAX_STREAM,
};
@@ -284,6 +288,7 @@ struct rkisp_capture_device {
struct rkisp_stream stream[RKISP_MAX_STREAM];
struct rkisp_buffer *rdbk_buf[RDBK_MAX];
struct rkisp_vir_cpy vir_cpy;
struct tasklet_struct rd_tasklet;
atomic_t refcnt;
u32 wait_line;
u32 wrap_line;

View File

@@ -19,6 +19,7 @@
*output->|->bypasspath----------------->ddr
* | |->bypasspath_4x4sampling->ddr
* |->selfpath------------------->ddr
* |->lumapath------------------->ddr
*/
#define CIF_ISP_REQ_BUFS_MIN 0
@@ -62,6 +63,22 @@ static const struct capture_fmt bp_fmts[] = {
}
};
static const struct capture_fmt luma_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_GREY,
.fmt_type = FMT_YUV,
.bpp = { 8 },
.cplanes = 1,
.mplanes = 1,
},
};
static struct stream_config rkisp_luma_stream_config = {
.fmts = luma_fmts,
.fmt_size = ARRAY_SIZE(luma_fmts),
.frame_end_id = 0,
};
static struct stream_config rkisp_bp_stream_config = {
.fmts = bp_fmts,
.fmt_size = ARRAY_SIZE(bp_fmts),
@@ -832,6 +849,89 @@ static int set_mirror_flip(struct rkisp_stream *stream)
return 0;
}
static void luma_frame_readout(unsigned long arg)
{
struct rkisp_stream *stream =
(struct rkisp_stream *)arg;
struct rkisp_device *dev = stream->ispdev;
unsigned long lock_flags = 0;
int timeout = 8;
u32 i, val, *data, seq;
u64 ns = 0;
stream->frame_end = false;
if (stream->stopping)
goto end;
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
if (!stream->curr_buf && !list_empty(&stream->buf_queue)) {
stream->curr_buf = list_first_entry(&stream->buf_queue,
struct rkisp_buffer, queue);
list_del(&stream->curr_buf->queue);
}
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
if (!stream->curr_buf) {
v4l2_warn(&dev->v4l2_dev, "%s no buf\n", __func__);
return;
}
rkisp_write(dev, ISP32_YNR_LUMA_RCTRL, ISP32_YNR_LUMA_RDBK_ST, true);
rkisp_dmarx_get_frame(dev, &seq, NULL, &ns, true);
while (timeout--) {
val = rkisp_read(dev, ISP32_YNR_LUMA_RCTRL, true);
if (val & ISP32_YNR_LUMA_RDBK_RDY)
break;
}
if (!timeout) {
v4l2_err(&dev->v4l2_dev, "%s no ready\n", __func__);
return;
}
val = stream->out_fmt.width * stream->out_fmt.height / 4;
data = stream->curr_buf->vaddr[0];
for (i = 0; i < val; i++) {
*data = rkisp_read(dev, ISP32_YNR_LUMA_RDATA, true);
data++;
}
if (!ns)
ns = ktime_get_ns();
stream->curr_buf->vb.vb2_buf.timestamp = ns;
stream->curr_buf->vb.sequence = seq;
vb2_set_plane_payload(&stream->curr_buf->vb.vb2_buf, 0, val * 4);
vb2_buffer_done(&stream->curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
stream->curr_buf = NULL;
end:
stream->frame_end = true;
if (stream->stopping) {
stream->stopping = false;
stream->streaming = false;
wake_up(&stream->done);
}
}
static int luma_frame_end(struct rkisp_stream *stream)
{
struct rkisp_device *dev = stream->ispdev;
u32 val;
if (!stream->streaming)
return 0;
val = rkisp_read(dev, ISP3X_YNR_GLOBAL_CTRL, true);
if (!(val & ISP3X_YNR_EN_SHD)) {
v4l2_warn(&dev->v4l2_dev, "%s YNR(0x%x) is off\n", __func__, val);
return -EINVAL;
}
if (IS_HDR_RDBK(dev->rd_mode))
luma_frame_readout((unsigned long)stream);
else
tasklet_schedule(&dev->cap_dev.rd_tasklet);
return 0;
}
static struct streams_ops rkisp_mp_streams_ops = {
.config_mi = mp_config_mi,
.enable_mi = mp_enable_mi,
@@ -884,6 +984,10 @@ static struct streams_ops rkisp_mpds_streams_ops = {
.frame_start = mi_frame_start,
};
static struct streams_ops rkisp_luma_streams_ops = {
.frame_end = luma_frame_end,
};
static int mi_frame_start(struct rkisp_stream *stream, u32 mis)
{
unsigned long lock_flags = 0;
@@ -975,7 +1079,7 @@ static void rkisp_stream_stop(struct rkisp_stream *stream)
stream->stopping = true;
stream->is_pause = false;
if (dev->hw_dev->is_single)
if (dev->hw_dev->is_single && stream->ops->disable_mi)
stream->ops->disable_mi(stream);
if (dev->isp_state & ISP_START &&
!stream->ops->is_stream_stopped(stream)) {
@@ -989,7 +1093,8 @@ static void rkisp_stream_stop(struct rkisp_stream *stream)
stream->stopping = false;
stream->streaming = false;
stream->ops->disable_mi(stream);
if (stream->ops->disable_mi)
stream->ops->disable_mi(stream);
if (stream->id == RKISP_STREAM_MP ||
stream->id == RKISP_STREAM_SP ||
stream->id == RKISP_STREAM_BP) {
@@ -1019,11 +1124,13 @@ static int rkisp_start(struct rkisp_stream *stream)
if (stream->ops->set_data_path)
stream->ops->set_data_path(stream);
ret = stream->ops->config_mi(stream);
if (ret)
return ret;
stream->ops->enable_mi(stream);
if (stream->ops->config_mi) {
ret = stream->ops->config_mi(stream);
if (ret)
return ret;
}
if (stream->ops->enable_mi)
stream->ops->enable_mi(stream);
if (is_update)
dev->irq_ends_mask |= get_stream_irq_mask(stream);
stream->streaming = true;
@@ -1090,7 +1197,7 @@ static void rkisp_buf_queue(struct vb2_buffer *vb)
memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr));
for (i = 0; i < isp_fmt->mplanes; i++) {
vb2_plane_vaddr(vb, i);
ispbuf->vaddr[i] = vb2_plane_vaddr(vb, i);
if (stream->ispdev->hw_dev->is_dma_sg_ops) {
sgt = vb2_dma_sg_plane_desc(vb, i);
@@ -1124,6 +1231,7 @@ static void rkisp_buf_queue(struct vb2_buffer *vb)
/* 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 = ispbuf;
stream->ops->update_mi(stream);
@@ -1198,6 +1306,18 @@ static void rkisp_stop_streaming(struct vb2_queue *queue)
if (!stream->streaming)
goto end;
if (stream->id == RKISP_STREAM_LUMA) {
stream->stopping = true;
wait_event_timeout(stream->done,
stream->frame_end,
msecs_to_jiffies(500));
stream->streaming = false;
stream->stopping = false;
destroy_buf_queue(stream, VB2_BUF_STATE_ERROR);
tasklet_disable(&dev->cap_dev.rd_tasklet);
goto end;
}
rkisp_stream_stop(stream);
if (!dev->cap_dev.wrap_line || atomic_read(&dev->cap_dev.refcnt) == 1) {
/* call to the other devices */
@@ -1278,6 +1398,13 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count)
}
memset(&stream->dbg, 0, sizeof(stream->dbg));
if (stream->id == RKISP_STREAM_LUMA) {
tasklet_enable(&dev->cap_dev.rd_tasklet);
stream->streaming = true;
goto end;
}
atomic_inc(&dev->cap_dev.refcnt);
if (!dev->isp_inp || !stream->linked) {
v4l2_err(v4l2_dev, "check %s link or isp input\n", node->vdev.name);
@@ -1340,7 +1467,7 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count)
goto pipe_stream_off;
}
}
end:
mutex_unlock(&dev->hw_dev->dev_lock);
return 0;
@@ -1433,6 +1560,16 @@ static int rkisp_stream_init(struct rkisp_device *dev, u32 id)
stream->config = &rkisp_mpds_stream_config;
stream->conn_id = RKISP_STREAM_MP;
break;
case RKISP_STREAM_LUMA:
strscpy(vdev->name, LUMA_VDEV_NAME, sizeof(vdev->name));
stream->ops = &rkisp_luma_streams_ops;
stream->config = &rkisp_luma_stream_config;
stream->conn_id = RKISP_STREAM_LUMA;
tasklet_init(&cap_dev->rd_tasklet,
luma_frame_readout,
(unsigned long)stream);
tasklet_disable(&cap_dev->rd_tasklet);
break;
default:
strscpy(vdev->name, MP_VDEV_NAME, sizeof(vdev->name));
stream->ops = &rkisp_mp_streams_ops;
@@ -1476,7 +1613,12 @@ int rkisp_register_stream_v32(struct rkisp_device *dev)
ret = rkisp_stream_init(dev, RKISP_STREAM_BPDS);
if (ret < 0)
goto err_free_mpds;
ret = rkisp_stream_init(dev, RKISP_STREAM_LUMA);
if (ret < 0)
goto err_free_bpds;
return 0;
err_free_bpds:
rkisp_unregister_stream_vdev(&cap_dev->stream[RKISP_STREAM_BPDS]);
err_free_mpds:
rkisp_unregister_stream_vdev(&cap_dev->stream[RKISP_STREAM_MPDS]);
err_free_bp:
@@ -1504,6 +1646,8 @@ void rkisp_unregister_stream_v32(struct rkisp_device *dev)
rkisp_unregister_stream_vdev(stream);
stream = &cap_dev->stream[RKISP_STREAM_BPDS];
rkisp_unregister_stream_vdev(stream);
stream = &cap_dev->stream[RKISP_STREAM_LUMA];
rkisp_unregister_stream_vdev(stream);
}
/**************** Interrupter Handler ****************/

View File

@@ -1872,6 +1872,10 @@
#define ISP3X_ISP_OUT_LINE(a) ((a) & 0x3fff)
#define ISP32_YNR_LUMA_RDBK_ST BIT(0)
#define ISP32_YNR_LUMA_RDBK_OFFS(a) (((a) & 0x3fff) << 16)
#define ISP32_YNR_LUMA_RDBK_RDY BIT(31)
/* DUAL CROP */
#define ISP3X_DUAL_CROP_FBC_MODE BIT(8)
@@ -2052,6 +2056,7 @@
#define ISP3X_CNR_GLOBAL_GAIN_ALPHA_MAX GENMASK(15, 12)
/* YNR */
#define ISP3X_YNR_EN_SHD BIT(31)
/* BLS */
#define ISP32_BLS_BLS2_EN BIT(5)

View File

@@ -2564,6 +2564,9 @@ static void rkisp_global_update_mi(struct rkisp_device *dev)
if (dev->hw_dev->is_single) {
for (i = 0; i < RKISP_MAX_STREAM; i++) {
stream = &dev->cap_dev.stream[i];
if (stream->id == RKISP_STREAM_VIR ||
stream->id == RKISP_STREAM_LUMA)
continue;
if (stream->streaming)
stream->ops->frame_end(stream);
}
@@ -3649,6 +3652,14 @@ vs_skip:
rkisp_config_cmsk(dev);
}
if (isp_mis & CIF_ISP_FRAME) {
if (dev->hw_dev->isp_ver == ISP_V32) {
struct rkisp_stream *s = &dev->cap_dev.stream[RKISP_STREAM_LUMA];
s->ops->frame_end(s);
}
}
/*
* Then update changed configs. Some of them involve
* lot of register writes. Do those only one per frame.