summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorCai YiWei <cyw@rock-chips.com>2018-11-23 18:52:31 +0800
committerTao Huang <huangtao@rock-chips.com>2019-01-03 19:04:50 +0800
commitc955146087d80e88be0c00d29af13618cffdb616 (patch)
treecc132e001066c4b331693b0edbbcbdbb5d0314af /drivers/media
parent725bdaa02495d4458300dd8874fd2e4d8297e0f8 (diff)
media: rockchip: isp1: isp v12/v13 add raw stream
stream raw support sensor bayer raw to mipi to dmatx to ddr. Change-Id: Ide24b6e9b2e5d95a6627cf046979ad62eeb9dea9 Signed-off-by: Cai YiWei <cyw@rock-chips.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/platform/rockchip/isp1/capture.c365
-rw-r--r--drivers/media/platform/rockchip/isp1/capture.h9
-rw-r--r--drivers/media/platform/rockchip/isp1/common.h4
-rw-r--r--drivers/media/platform/rockchip/isp1/dev.c16
-rw-r--r--drivers/media/platform/rockchip/isp1/dev.h1
-rw-r--r--drivers/media/platform/rockchip/isp1/regs.h97
-rw-r--r--drivers/media/platform/rockchip/isp1/rkisp1.c2
7 files changed, 461 insertions, 33 deletions
diff --git a/drivers/media/platform/rockchip/isp1/capture.c b/drivers/media/platform/rockchip/isp1/capture.c
index b31b97a4aed4..da89d5467112 100644
--- a/drivers/media/platform/rockchip/isp1/capture.c
+++ b/drivers/media/platform/rockchip/isp1/capture.c
@@ -526,6 +526,71 @@ static const struct capture_fmt sp_fmts[] = {
},
};
+static const struct capture_fmt raw_fmts[] = {
+ /* raw */
+ {
+ .fourcc = V4L2_PIX_FMT_SRGGB8,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 8 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGRBG8,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 8 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGBRG8,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 8 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SBGGR8,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 8 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SRGGB8,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 10 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGRBG10,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 10 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGBRG10,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 10 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SBGGR10,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 10 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SRGGB12,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 12 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGRBG12,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 12 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SGBRG12,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 12 },
+ .mplanes = 1,
+ }, {
+ .fourcc = V4L2_PIX_FMT_SBGGR12,
+ .fmt_type = FMT_BAYER,
+ .bpp = { 12 },
+ .mplanes = 1,
+ },
+};
+
static struct stream_config rkisp1_mp_stream_config = {
.fmts = mp_fmts,
.fmt_size = ARRAY_SIZE(mp_fmts),
@@ -636,6 +701,11 @@ static struct stream_config rkisp1_sp_stream_config = {
},
};
+static struct stream_config rkisp1_raw_stream_config = {
+ .fmts = raw_fmts,
+ .fmt_size = ARRAY_SIZE(mp_fmts),
+};
+
static const
struct capture_fmt *find_fmt(struct rkisp1_stream *stream, const u32 pixelfmt)
{
@@ -688,7 +758,8 @@ static int rkisp1_config_rsz(struct rkisp1_stream *stream, bool async)
struct ispsd_out_fmt *input_isp_fmt =
rkisp1_get_ispsd_out_fmt(&dev->isp_sdev);
struct v4l2_rect in_y, in_c, out_y, out_c;
- u32 xsubs_in, ysubs_in, xsubs_out, ysubs_out;
+ u32 xsubs_in = 1, ysubs_in = 1;
+ u32 xsubs_out = 1, ysubs_out = 1;
if (input_isp_fmt->fmt_type == FMT_BAYER)
goto disable;
@@ -868,6 +939,51 @@ static int sp_config_mi(struct rkisp1_stream *stream)
return 0;
}
+/*
+ * configure memory interface for rawpath
+ * This should only be called when stream-on
+ */
+static int raw_config_mi(struct rkisp1_stream *stream)
+{
+ void __iomem *base = stream->ispdev->base_addr;
+ struct rkisp1_device *dev = stream->ispdev;
+ struct v4l2_mbus_framefmt *in_frm =
+ &dev->active_sensor->fmt.format;
+
+ v4l2_dbg(1, rkisp1_debug, &dev->v4l2_dev,
+ "stream:%d input %dx%d\n",
+ stream->id, in_frm->width, in_frm->height);
+
+ if (dev->active_sensor->mbus.type != V4L2_MBUS_CSI2) {
+ if (stream->id == RKISP1_STREAM_RAW)
+ v4l2_err(&dev->v4l2_dev,
+ "only mipi sensor support raw path\n");
+ return -EINVAL;
+ }
+
+ if (dev->stream[RKISP1_STREAM_RAW].streaming)
+ return 0;
+
+ /* raw output size equal to sensor input size */
+ dmatx0_set_pic_size(base, in_frm->width, in_frm->height);
+ dmatx0_set_pic_off(base, 0);
+ dmatx0_ctrl(base,
+ CIF_ISP_CSI0_DMATX0_VC(1) |
+ CIF_ISP_CSI0_DMATX0_SIMG_SWP |
+ CIF_ISP_CSI0_DMATX0_SIMG_MODE);
+ mi_raw0_set_size(base, in_frm->height * in_frm->width * 2);
+ mi_raw0_set_offs(base, 0);
+ mi_raw0_set_length(base, 0);
+ mi_raw0_set_irq_offs(base, 0);
+ /* dummy buf for raw first address shadow */
+ mi_raw0_set_addr(base, stream->dummy_buf.dma_addr);
+ mi_ctrl2(base, CIF_MI_CTRL2_MIPI_RAW0_AUTO_UPDATE);
+ if (stream->id == RKISP1_STREAM_RAW)
+ stream->u.raw.pre_stop = false;
+
+ return 0;
+}
+
static void mp_enable_mi(struct rkisp1_stream *stream)
{
void __iomem *base = stream->ispdev->base_addr;
@@ -887,6 +1003,13 @@ static void sp_enable_mi(struct rkisp1_stream *stream)
mi_ctrl_spyuv_enable(base);
}
+static void raw_enable_mi(struct rkisp1_stream *stream)
+{
+ void __iomem *base = stream->ispdev->base_addr;
+
+ mi_mipi_raw0_enable(base);
+}
+
static void mp_disable_mi(struct rkisp1_stream *stream)
{
void __iomem *base = stream->ispdev->base_addr;
@@ -901,6 +1024,18 @@ static void sp_disable_mi(struct rkisp1_stream *stream)
mi_ctrl_spyuv_disable(base);
}
+static void update_dmatx0(struct rkisp1_stream *stream)
+{
+ void __iomem *base = stream->ispdev->base_addr;
+ struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
+
+ if (stream->next_buf)
+ mi_raw0_set_addr(base,
+ stream->next_buf->buff_addr[RKISP1_PLANE_Y]);
+ else
+ mi_raw0_set_addr(base, dummy_buf->dma_addr);
+}
+
/* Update buffer info to memory interface, it's called in interrupt */
static void update_mi(struct rkisp1_stream *stream)
{
@@ -945,6 +1080,15 @@ static void sp_stop_mi(struct rkisp1_stream *stream)
stream->ops->disable_mi(stream);
}
+static void raw_stop_mi(struct rkisp1_stream *stream)
+{
+ void __iomem *base = stream->ispdev->base_addr;
+
+ if (!stream->streaming)
+ return;
+ mi_mipi_raw0_disable(base);
+}
+
static struct streams_ops rkisp1_mp_streams_ops = {
.config_mi = mp_config_mi,
.enable_mi = mp_enable_mi,
@@ -952,6 +1096,7 @@ static struct streams_ops rkisp1_mp_streams_ops = {
.stop_mi = mp_stop_mi,
.set_data_path = mp_set_data_path,
.is_stream_stopped = mp_is_stream_stopped,
+ .update_mi = update_mi,
};
static struct streams_ops rkisp1_sp_streams_ops = {
@@ -961,6 +1106,14 @@ static struct streams_ops rkisp1_sp_streams_ops = {
.stop_mi = sp_stop_mi,
.set_data_path = sp_set_data_path,
.is_stream_stopped = sp_is_stream_stopped,
+ .update_mi = update_mi,
+};
+
+static struct streams_ops rkisp1_raw_streams_ops = {
+ .config_mi = raw_config_mi,
+ .enable_mi = raw_enable_mi,
+ .stop_mi = raw_stop_mi,
+ .update_mi = update_dmatx0,
};
/*
@@ -1008,7 +1161,7 @@ static int mi_frame_end(struct rkisp1_stream *stream)
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
- update_mi(stream);
+ stream->ops->update_mi(stream);
return 0;
}
@@ -1035,8 +1188,10 @@ static void rkisp1_stream_stop(struct rkisp1_stream *stream)
stream->stopping = false;
stream->streaming = false;
}
- disable_dcrop(stream, true);
- disable_rsz(stream, true);
+ if (stream->id != RKISP1_STREAM_RAW) {
+ disable_dcrop(stream, true);
+ disable_rsz(stream, true);
+ }
stream->burst =
CIF_MI_CTRL_BURST_LEN_LUM_16 |
CIF_MI_CTRL_BURST_LEN_CHROM_16;
@@ -1052,16 +1207,39 @@ static int rkisp1_start(struct rkisp1_stream *stream)
{
void __iomem *base = stream->ispdev->base_addr;
struct rkisp1_device *dev = stream->ispdev;
- struct rkisp1_stream *other = &dev->stream[stream->id ^ 1];
- int ret;
+ bool other_streaming = false;
+ int i, ret;
+
+ for (i = 0; i < RKISP1_MAX_STREAM; i++) {
+ if (i != stream->id &&
+ dev->stream[i].streaming) {
+ other_streaming = true;
+ break;
+ }
+ }
+
+ /* stream raw need mi_cfg_upd to update first base address shadow
+ * config raw in first stream (sp/mp), and enable when raw stream open.
+ */
+ if (!other_streaming &&
+ stream->id == RKISP1_STREAM_RAW) {
+ v4l2_err(&dev->v4l2_dev,
+ "stream raw only support to open after stream mp/sp");
+ return -EINVAL;
+ }
+ if (dev->isp_ver == ISP_V12 ||
+ dev->isp_ver == ISP_V13)
+ raw_config_mi(stream);
- stream->ops->set_data_path(base);
+ if (stream->ops->set_data_path)
+ stream->ops->set_data_path(base);
ret = stream->ops->config_mi(stream);
if (ret)
return ret;
- /* Set up an buffer for the next frame */
- mi_frame_end(stream);
+ /* for mp/sp Set up an buffer for the next frame */
+ if (stream->id != RKISP1_STREAM_RAW)
+ mi_frame_end(stream);
stream->ops->enable_mi(stream);
/* It's safe to config ACTIVE and SHADOW regs for the
* first stream. While when the second is starting, do NOT
@@ -1072,7 +1250,7 @@ static int rkisp1_start(struct rkisp1_stream *stream)
* also required because the sencond FE maybe corrupt especially
* when run at 120fps.
*/
- if (!other->streaming) {
+ if (!other_streaming) {
force_cfg_update(base);
mi_frame_end(stream);
}
@@ -1135,8 +1313,17 @@ static void rkisp1_buf_queue(struct vb2_buffer *vb)
int i;
memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr));
- for (i = 0; i < isp_fmt->mplanes; i++)
+ for (i = 0; i < isp_fmt->mplanes; i++) {
ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
+ if (stream->id == RKISP1_STREAM_RAW) {
+ /* for check dmatx to ddr complete */
+ u32 sizeimage = pixm->plane_fmt[0].sizeimage;
+ u32 *buf = vb2_plane_vaddr(vb, 0);
+
+ *buf = RKISP1_DMATX_CHECK;
+ *(buf + sizeimage / 4 - 1) = RKISP1_DMATX_CHECK;
+ }
+ }
/*
* NOTE: plane_fmt[0].sizeimage is total size of all planes for single
@@ -1158,9 +1345,10 @@ static void rkisp1_buf_queue(struct vb2_buffer *vb)
/* XXX: replace dummy to speed up */
if (stream->streaming &&
stream->next_buf == NULL &&
+ stream->id != RKISP1_STREAM_RAW &&
atomic_read(&stream->ispdev->isp_sdev.frm_sync_seq) == 0) {
stream->next_buf = ispbuf;
- update_mi(stream);
+ stream->ops->update_mi(stream);
} else {
list_add_tail(&ispbuf->queue, &stream->buf_queue);
}
@@ -1171,12 +1359,21 @@ static int rkisp1_create_dummy_buf(struct rkisp1_stream *stream)
{
struct rkisp1_dummy_buffer *dummy_buf = &stream->dummy_buf;
struct rkisp1_device *dev = stream->ispdev;
+ struct v4l2_mbus_framefmt *in_frm = NULL;
+ u32 in_size;
/* get a maximum size */
dummy_buf->size = max3(stream->out_fmt.plane_fmt[0].bytesperline *
stream->out_fmt.height,
stream->out_fmt.plane_fmt[1].sizeimage,
stream->out_fmt.plane_fmt[2].sizeimage);
+ if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2 &&
+ (dev->isp_ver == ISP_V12 ||
+ dev->isp_ver == ISP_V13)) {
+ in_frm = &dev->active_sensor->fmt.format;
+ in_size = in_frm->height * in_frm->width * 2;
+ dummy_buf->size = max(dummy_buf->size, in_size);
+ }
dummy_buf->vaddr = dma_alloc_coherent(dev->dev, dummy_buf->size,
&dummy_buf->dma_addr,
@@ -1249,6 +1446,10 @@ static int rkisp1_stream_start(struct rkisp1_stream *stream)
bool async = false;
int ret;
+ /* STREAM RAW don't have rsz and dcrop */
+ if (stream->id == RKISP1_STREAM_RAW)
+ goto end;
+
if (other->streaming)
async = true;
@@ -1268,6 +1469,7 @@ static int rkisp1_stream_start(struct rkisp1_stream *stream)
return ret;
}
+end:
return rkisp1_start(stream);
}
@@ -1372,22 +1574,30 @@ static void rkisp1_set_fmt(struct rkisp1_stream *stream,
{
const struct capture_fmt *fmt;
const struct stream_config *config = stream->config;
- struct rkisp1_stream *other_stream =
- &stream->ispdev->stream[!stream->id];
+ struct rkisp1_stream *other_stream;
unsigned int imagsize = 0;
unsigned int planes;
u32 xsubs = 1, ysubs = 1;
- int i;
+ unsigned int i;
fmt = find_fmt(stream, pixm->pixelformat);
if (!fmt)
fmt = config->fmts;
- /* do checks on resolution */
- pixm->width = clamp_t(u32, pixm->width, config->min_rsz_width,
- config->max_rsz_width);
- pixm->height = clamp_t(u32, pixm->height, config->min_rsz_height,
- config->max_rsz_height);
+ if (stream->id != RKISP1_STREAM_RAW) {
+ other_stream =
+ &stream->ispdev->stream[!stream->id ^ 1];
+ /* do checks on resolution */
+ pixm->width = clamp_t(u32, pixm->width,
+ config->min_rsz_width,
+ config->max_rsz_width);
+ pixm->height = clamp_t(u32, pixm->height,
+ config->min_rsz_height,
+ config->max_rsz_height);
+ } else {
+ other_stream =
+ &stream->ispdev->stream[RKISP1_STREAM_MP];
+ }
pixm->num_planes = fmt->mplanes;
pixm->field = V4L2_FIELD_NONE;
/* get quantization from ispsd */
@@ -1405,7 +1615,7 @@ static void rkisp1_set_fmt(struct rkisp1_stream *stream,
planes = fmt->cplanes ? fmt->cplanes : fmt->mplanes;
for (i = 0; i < planes; i++) {
struct v4l2_plane_pix_format *plane_fmt;
- int width, height, bytesperline;
+ unsigned int width, height, bytesperline;
plane_fmt = pixm->plane_fmt + i;
@@ -1443,9 +1653,10 @@ static void rkisp1_set_fmt(struct rkisp1_stream *stream,
stream->u.sp.y_stride =
pixm->plane_fmt[0].bytesperline /
DIV_ROUND_UP(fmt->bpp[0], 8);
- } else {
+ } else if (stream->id == RKISP1_STREAM_MP) {
stream->u.mp.raw_enable = (fmt->fmt_type == FMT_BAYER);
}
+
v4l2_dbg(1, rkisp1_debug, &stream->ispdev->v4l2_dev,
"%s: stream: %d req(%d, %d) out(%d, %d)\n", __func__,
stream->id, pixm->width, pixm->height,
@@ -1544,6 +1755,9 @@ void rkisp1_stream_init(struct rkisp1_device *dev, u32 id)
if (stream->id == RKISP1_STREAM_SP) {
stream->ops = &rkisp1_sp_streams_ops;
stream->config = &rkisp1_sp_stream_config;
+ } else if (stream->id == RKISP1_STREAM_RAW) {
+ stream->ops = &rkisp1_raw_streams_ops;
+ stream->config = &rkisp1_raw_stream_config;
} else {
stream->ops = &rkisp1_mp_streams_ops;
stream->config = &rkisp1_mp_stream_config;
@@ -1668,9 +1882,10 @@ static struct v4l2_rect *rkisp1_update_crop(struct rkisp1_stream *stream,
struct v4l2_rect *sel,
const struct v4l2_rect *in)
{
- /* Not crop for MP bayer raw data */
- if (stream->id == RKISP1_STREAM_MP &&
- stream->out_isp_fmt.fmt_type == FMT_BAYER) {
+ /* Not crop for MP bayer raw data and RAW path */
+ if ((stream->id == RKISP1_STREAM_MP &&
+ stream->out_isp_fmt.fmt_type == FMT_BAYER) ||
+ stream->id == RKISP1_STREAM_RAW) {
sel->left = 0;
sel->top = 0;
sel->width = in->width;
@@ -1768,9 +1983,13 @@ void rkisp1_unregister_stream_vdevs(struct rkisp1_device *dev)
{
struct rkisp1_stream *mp_stream = &dev->stream[RKISP1_STREAM_MP];
struct rkisp1_stream *sp_stream = &dev->stream[RKISP1_STREAM_SP];
+ struct rkisp1_stream *raw_stream = &dev->stream[RKISP1_STREAM_RAW];
rkisp1_unregister_stream_vdev(mp_stream);
rkisp1_unregister_stream_vdev(sp_stream);
+ if (dev->isp_ver == ISP_V12 ||
+ dev->isp_ver == ISP_V13)
+ rkisp1_unregister_stream_vdev(raw_stream);
}
static int rkisp1_register_stream_vdev(struct rkisp1_stream *stream)
@@ -1779,11 +1998,27 @@ static int rkisp1_register_stream_vdev(struct rkisp1_stream *stream)
struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
struct video_device *vdev = &stream->vnode.vdev;
struct rkisp1_vdev_node *node;
- int ret;
+ int ret = 0;
+ char *vdev_name;
- strlcpy(vdev->name,
- stream->id == RKISP1_STREAM_SP ? SP_VDEV_NAME : MP_VDEV_NAME,
- sizeof(vdev->name));
+ switch (stream->id) {
+ case RKISP1_STREAM_SP:
+ vdev_name = SP_VDEV_NAME;
+ break;
+ case RKISP1_STREAM_MP:
+ vdev_name = MP_VDEV_NAME;
+ break;
+ case RKISP1_STREAM_RAW:
+ vdev_name = RAW_VDEV_NAME;
+ if (dev->isp_ver != ISP_V12 &&
+ dev->isp_ver != ISP_V13)
+ return 0;
+ break;
+ default:
+ v4l2_err(v4l2_dev, "Invalid stream\n");
+ goto unreg;
+ }
+ strlcpy(vdev->name, vdev_name, sizeof(vdev->name));
node = vdev_to_node(vdev);
mutex_init(&node->vlock);
@@ -1847,7 +2082,7 @@ err:
void rkisp1_mi_isr(u32 mis_val, struct rkisp1_device *dev)
{
- int i;
+ unsigned int i;
for (i = 0; i < ARRAY_SIZE(dev->stream); ++i) {
struct rkisp1_stream *stream = &dev->stream[i];
@@ -1878,3 +2113,73 @@ void rkisp1_mi_isr(u32 mis_val, struct rkisp1_device *dev)
}
}
}
+
+void rkisp1_mipi_dmatx0_end(u32 status, struct rkisp1_device *dev)
+{
+ struct rkisp1_stream *stream = &dev->stream[RKISP1_STREAM_RAW];
+ u32 *buf, end, timeout = 100;
+
+ if (!(status & 0x1) || !stream->streaming)
+ return;
+
+ dmatx0_enable(dev->base_addr);
+ if (stream->stopping) {
+ /* update dmatx buf to other stream dummy buf if other
+ * stream don't close, but dmatx is reopen.
+ * dmatx first buf will write to this.
+ */
+ if (!stream->u.raw.pre_stop) {
+ int i;
+ struct rkisp1_stream *other = NULL;
+
+ for (i = 0; i < RKISP1_MAX_STREAM; i++) {
+ if (i != stream->id &&
+ dev->stream[i].streaming) {
+ other = &dev->stream[i];
+ break;
+ }
+ }
+
+ stream->u.raw.pre_stop = true;
+ if (other) {
+ mi_raw0_set_addr(dev->base_addr,
+ other->dummy_buf.dma_addr);
+ return;
+ }
+ }
+
+ if (stream->u.raw.pre_stop) {
+ dmatx0_disable(dev->base_addr);
+ stream->u.raw.pre_stop = false;
+ stream->stopping = false;
+ stream->streaming = false;
+ wake_up(&stream->done);
+ }
+ } else {
+ if (stream->curr_buf) {
+ /* for check dmatx to ddr complete */
+ u32 sizeimage = stream->out_fmt.plane_fmt[0].sizeimage;
+
+ buf = (u32 *)vb2_plane_vaddr(&stream->curr_buf->vb.vb2_buf, 0);
+ end = *(buf + sizeimage / 4 - 1);
+ while (end == RKISP1_DMATX_CHECK) {
+ udelay(1);
+ end = *(buf + sizeimage / 4 - 1);
+ if (timeout-- == 0) {
+ /* if shd don't update
+ * check aclk_isp >= clk_isp
+ * input equal to sensor output, no crop
+ */
+ v4l2_err(&dev->v4l2_dev,
+ "dmatx to ddr timeout!\n"
+ "base:0x%x shd:0x%x data:0x%x~0x%x\n",
+ readl(dev->base_addr + CIF_MI_RAW0_BASE_AD_INIT),
+ readl(dev->base_addr + CIF_MI_RAW0_BASE_AS_SHD),
+ *buf, end);
+ break;
+ }
+ }
+ }
+ mi_frame_end(stream);
+ }
+}
diff --git a/drivers/media/platform/rockchip/isp1/capture.h b/drivers/media/platform/rockchip/isp1/capture.h
index ef1eb7a1d490..3a249c862820 100644
--- a/drivers/media/platform/rockchip/isp1/capture.h
+++ b/drivers/media/platform/rockchip/isp1/capture.h
@@ -79,6 +79,10 @@ struct rkisp1_stream_mp {
bool raw_enable;
};
+struct rkisp1_stream_raw {
+ u8 pre_stop;
+};
+
/* Different config between selfpath and mainpath */
struct stream_config {
const struct capture_fmt *fmts;
@@ -143,6 +147,7 @@ struct streams_ops {
void (*disable_mi)(struct rkisp1_stream *stream);
void (*set_data_path)(void __iomem *base);
bool (*is_stream_stopped)(void __iomem *base);
+ void (*update_mi)(struct rkisp1_stream *stream);
};
/*
@@ -161,7 +166,7 @@ struct streams_ops {
* @next_buf: the buffer used for next frame
*/
struct rkisp1_stream {
- unsigned id:1;
+ unsigned id:2;
struct rkisp1_device *ispdev;
struct rkisp1_vdev_node vnode;
struct capture_fmt out_isp_fmt;
@@ -181,6 +186,7 @@ struct rkisp1_stream {
union {
struct rkisp1_stream_sp sp;
struct rkisp1_stream_mp mp;
+ struct rkisp1_stream_raw raw;
} u;
};
@@ -190,5 +196,6 @@ void rkisp1_mi_isr(u32 mis_val, struct rkisp1_device *dev);
void rkisp1_stream_init(struct rkisp1_device *dev, u32 id);
void rkisp1_set_stream_def_fmt(struct rkisp1_device *dev, u32 id,
u32 width, u32 height, u32 pixelformat);
+void rkisp1_mipi_dmatx0_end(u32 status, struct rkisp1_device *dev);
#endif /* _RKISP1_PATH_VIDEO_H */
diff --git a/drivers/media/platform/rockchip/isp1/common.h b/drivers/media/platform/rockchip/isp1/common.h
index bda09cc07717..d2c606461886 100644
--- a/drivers/media/platform/rockchip/isp1/common.h
+++ b/drivers/media/platform/rockchip/isp1/common.h
@@ -45,15 +45,17 @@
#define RKISP1_DEFAULT_WIDTH 800
#define RKISP1_DEFAULT_HEIGHT 600
-#define RKISP1_MAX_STREAM 2
+#define RKISP1_MAX_STREAM 3
#define RKISP1_STREAM_MP 0
#define RKISP1_STREAM_SP 1
+#define RKISP1_STREAM_RAW 2
#define RKISP1_PLANE_Y 0
#define RKISP1_PLANE_CB 1
#define RKISP1_PLANE_CR 2
#define RKISP1_EMDDATA_FIFO_MAX 4
+#define RKISP1_DMATX_CHECK 0xA5A5A5A5
enum rkisp1_sd_type {
RKISP1_SD_SENSOR,
diff --git a/drivers/media/platform/rockchip/isp1/dev.c b/drivers/media/platform/rockchip/isp1/dev.c
index 932b27e92ffc..1984e01bc236 100644
--- a/drivers/media/platform/rockchip/isp1/dev.c
+++ b/drivers/media/platform/rockchip/isp1/dev.c
@@ -355,6 +355,17 @@ static int rkisp1_create_links(struct rkisp1_device *dev)
if (ret < 0)
return ret;
+ if (dev->isp_ver == ISP_V12 ||
+ dev->isp_ver == ISP_V13) {
+ /* MIPI RAW links */
+ source = &dev->isp_sdev.sd.entity;
+ sink = &dev->stream[RKISP1_STREAM_RAW].vnode.vdev.entity;
+ ret = media_entity_create_link(source,
+ RKISP1_ISP_PAD_SOURCE_PATH, sink, 0, flags);
+ if (ret < 0)
+ return ret;
+ }
+
/* 3A stats links */
source = &dev->isp_sdev.sd.entity;
sink = &dev->stats_vdev.vnode.vdev.entity;
@@ -653,6 +664,8 @@ static irqreturn_t rkisp1_mipi_irq_hdl(int irq, void *ctx)
err2 = readl(rkisp1_dev->base_addr + CIF_ISP_CSI0_ERR2);
err3 = readl(rkisp1_dev->base_addr + CIF_ISP_CSI0_ERR3);
+ if (err3 & 0x1)
+ rkisp1_mipi_dmatx0_end(err3, rkisp1_dev);
if (err1 || err2 || err3)
rkisp1_mipi_v13_isr(err1, err2, err3, rkisp1_dev);
} else {
@@ -697,7 +710,7 @@ static const char * const rk3399_isp_clks[] = {
/* isp clock adjustment table (MHz) */
static const unsigned int rk1808_isp_clk_rate[] = {
- 400, 500, 600
+ 300, 400, 500, 600
};
/* isp clock adjustment table (MHz) */
@@ -1004,6 +1017,7 @@ static int rkisp1_plat_probe(struct platform_device *pdev)
rkisp1_stream_init(isp_dev, RKISP1_STREAM_SP);
rkisp1_stream_init(isp_dev, RKISP1_STREAM_MP);
+ rkisp1_stream_init(isp_dev, RKISP1_STREAM_RAW);
strlcpy(isp_dev->media_dev.model, "rkisp1",
sizeof(isp_dev->media_dev.model));
diff --git a/drivers/media/platform/rockchip/isp1/dev.h b/drivers/media/platform/rockchip/isp1/dev.h
index ea5c1b93bcc7..60209e1ba0e2 100644
--- a/drivers/media/platform/rockchip/isp1/dev.h
+++ b/drivers/media/platform/rockchip/isp1/dev.h
@@ -45,6 +45,7 @@
#define SP_VDEV_NAME DRIVER_NAME "_selfpath"
#define MP_VDEV_NAME DRIVER_NAME "_mainpath"
#define DMA_VDEV_NAME DRIVER_NAME "_dmapath"
+#define RAW_VDEV_NAME DRIVER_NAME "_rawpath"
#define GRP_ID_SENSOR BIT(0)
#define GRP_ID_MIPIPHY BIT(1)
diff --git a/drivers/media/platform/rockchip/isp1/regs.h b/drivers/media/platform/rockchip/isp1/regs.h
index bda9f749dd96..3b4b30a4e8af 100644
--- a/drivers/media/platform/rockchip/isp1/regs.h
+++ b/drivers/media/platform/rockchip/isp1/regs.h
@@ -188,6 +188,11 @@
#define CIF_MI_CTRL_SHD_JPEG_OUT_ENABLED BIT(18)
#define CIF_MI_CTRL_SHD_RAW_OUT_ENABLED BIT(19)
+/* MI_CTRL2 */
+#define CIF_MI_CTRL2_MIPI_RAW0_PINGPONG_EN BIT(2)
+#define CIF_MI_CTRL2_MIPI_RAW0_AUTO_UPDATE BIT(1)
+#define CIF_MI_CTRL2_MIPI_RAW0_ENABLE BIT(0)
+
/* RSZ_CTRL */
#define CIF_RSZ_CTRL_SCALE_HY_ENABLE BIT(0)
#define CIF_RSZ_CTRL_SCALE_HC_ENABLE BIT(1)
@@ -728,6 +733,11 @@
#define CIF_ISP_CSI0_IMASK_RAW0_OUT_V_END BIT(10)
#define CIF_ISP_CSI0_IMASK_FRAME_END(a) (((a) & 0x3F) << 0)
+#define CIF_ISP_CSI0_DMATX0_VC(a) (((a) & 0xFF) << 8)
+#define CIF_ISP_CSI0_DMATX0_SIMG_SWP BIT(2)
+#define CIF_ISP_CSI0_DMATX0_SIMG_MODE BIT(1)
+#define CIF_ISP_CSI0_DMATX0_EN BIT(0)
+
/* =================================================================== */
/* CIF Registers */
/* =================================================================== */
@@ -1077,6 +1087,18 @@
#define CIF_MI_SP_CB_BASE_AD_INIT2 (CIF_MI_BASE + 0x00000140)
#define CIF_MI_SP_CR_BASE_AD_INIT2 (CIF_MI_BASE + 0x00000144)
#define CIF_MI_XTD_FORMAT_CTRL (CIF_MI_BASE + 0x00000148)
+#define CIF_MI_CTRL2 (CIF_MI_BASE + 0x00000150)
+#define CIF_MI_RAW0_BASE_AD_INIT (CIF_MI_BASE + 0x00000160)
+#define CIF_MI_RAW0_BASE_AD_INIT2 (CIF_MI_BASE + 0x00000164)
+#define CIF_MI_RAW0_IRQ_OFFS_INIT (CIF_MI_BASE + 0x00000168)
+#define CIF_MI_RAW0_SIZE_INIT (CIF_MI_BASE + 0x0000016c)
+#define CIF_MI_RAW0_OFFS_CNT_INIT (CIF_MI_BASE + 0x00000170)
+#define CIF_MI_RAW0_LENGTH (CIF_MI_BASE + 0x00000174)
+#define CIF_MI_RAW0_OFFS_CNT_START_SHD (CIF_MI_BASE + 0x00000178)
+#define CIF_MI_RAW0_BASE_AS_SHD (CIF_MI_BASE + 0x00000180)
+#define CIF_MI_RAW0_IRQ_OFFS_INI_SHD (CIF_MI_BASE + 0x00000184)
+#define CIF_MI_RAW0_SIZE_INIT_SHD (CIF_MI_BASE + 0x00000188)
+#define CIF_MI_RAW0_OFFS_CNT_INIT_SHD (CIF_MI_BASE + 0x0000018c)
#define CIF_SMIA_BASE 0x00001A00
#define CIF_SMIA_CTRL (CIF_SMIA_BASE + 0x00000000)
@@ -1732,4 +1754,79 @@ static inline void force_cfg_update(void __iomem *base)
writel(CIF_MI_INIT_SOFT_UPD, base + CIF_MI_INIT);
}
+static inline void dmatx0_ctrl(void __iomem *base, u32 val)
+{
+ writel(val, base + CIF_ISP_CSI0_DMATX0_CTRL);
+}
+
+static inline void dmatx0_enable(void __iomem *base)
+{
+ void __iomem *addr = base + CIF_ISP_CSI0_DMATX0_CTRL;
+
+ writel(CIF_ISP_CSI0_DMATX0_EN | readl(addr), addr);
+}
+
+static inline void dmatx0_disable(void __iomem *base)
+{
+ void __iomem *addr = base + CIF_ISP_CSI0_DMATX0_CTRL;
+
+ writel(~CIF_ISP_CSI0_DMATX0_EN & readl(addr), addr);
+}
+
+static inline void dmatx0_set_pic_size(void __iomem *base,
+ u32 width, u32 height)
+{
+ writel(height << 16 | width,
+ base + CIF_ISP_CSI0_DMATX0_PIC_SIZE);
+}
+
+static inline void dmatx0_set_pic_off(void __iomem *base, u32 val)
+{
+ writel(val, base + CIF_ISP_CSI0_DMATX0_PIC_OFF);
+}
+
+static inline void mi_raw0_set_size(void __iomem *base, u32 val)
+{
+ writel(val, base + CIF_MI_RAW0_SIZE_INIT);
+}
+
+static inline void mi_raw0_set_offs(void __iomem *base, u32 val)
+{
+ writel(val, base + CIF_MI_RAW0_OFFS_CNT_INIT);
+}
+
+static inline void mi_raw0_set_length(void __iomem *base, u32 val)
+{
+ writel(val, base + CIF_MI_RAW0_LENGTH);
+}
+
+static inline void mi_raw0_set_irq_offs(void __iomem *base, u32 val)
+{
+ writel(val, base + CIF_MI_RAW0_IRQ_OFFS_INIT);
+}
+
+static inline void mi_raw0_set_addr(void __iomem *base, u32 val)
+{
+ writel(val, base + CIF_MI_RAW0_BASE_AD_INIT);
+}
+
+static inline void mi_mipi_raw0_enable(void __iomem *base)
+{
+ void __iomem *addr = base + CIF_MI_CTRL2;
+
+ writel(CIF_MI_CTRL2_MIPI_RAW0_ENABLE | readl(addr), addr);
+}
+
+static inline void mi_mipi_raw0_disable(void __iomem *base)
+{
+ void __iomem *addr = base + CIF_MI_CTRL2;
+
+ writel(~CIF_MI_CTRL2_MIPI_RAW0_ENABLE & readl(addr), addr);
+}
+
+static inline void mi_ctrl2(void __iomem *base, u32 val)
+{
+ writel(val, base + CIF_MI_CTRL2);
+}
+
#endif /* _RKISP1_REGS_H */
diff --git a/drivers/media/platform/rockchip/isp1/rkisp1.c b/drivers/media/platform/rockchip/isp1/rkisp1.c
index 5a0e5f81b6fc..e0559fc114bf 100644
--- a/drivers/media/platform/rockchip/isp1/rkisp1.c
+++ b/drivers/media/platform/rockchip/isp1/rkisp1.c
@@ -411,6 +411,8 @@ static int rkisp1_config_mipi(struct rkisp1_device *dev)
/* interrupts */
writel(CIF_ISP_CSI0_IMASK_FRAME_END(0x3F) |
+ CIF_ISP_CSI0_IMASK_RAW0_OUT_V_END |
+ CIF_ISP_CSI0_IMASK_RAW1_OUT_V_END |
CIF_ISP_CSI0_IMASK_LINECNT,
base + CIF_ISP_CSI0_MASK3);