mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
media: rockchip/cif: support capture mipi csi data for rk1808
Also add support pingpong frame mode. Change-Id: Ibc29e3452351ae6ffafebbf72386b47bfb853f8c Signed-off-by: Wenlong Zhuang <daisen.zhuang@rock-chips.com>
This commit is contained in:
committed by
Tao Huang
parent
7cc71c2e2f
commit
573f0547a8
@@ -83,6 +83,81 @@ static const struct cif_output_fmt out_fmts[] = {
|
||||
.cplanes = 2,
|
||||
.mplanes = 1,
|
||||
.bpp = { 8, 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_RGB24,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 24 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_BGR666,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 18 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SRGGB8,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 8 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SGRBG8,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 8 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SGBRG8,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 8 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SBGGR8,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 8 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SRGGB10,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SGRBG10,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SGBRG10,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SBGGR10,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SRGGB12,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SGRBG12,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SGBRG12,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
}, {
|
||||
.fourcc = V4L2_PIX_FMT_SBGGR12,
|
||||
.cplanes = 1,
|
||||
.mplanes = 1,
|
||||
.bpp = { 16 },
|
||||
},
|
||||
|
||||
/* TODO: We can support NV12M/NV21M/NV16M/NV61M too */
|
||||
@@ -105,6 +180,45 @@ static const struct cif_input_fmt in_fmts[] = {
|
||||
.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
|
||||
.fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_VYUY,
|
||||
.fmt_type = CIF_FMT_TYPE_YUV,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW8,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW8,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW8,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW8,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW10,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW10,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW10,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW10,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW12,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW12,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW12,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RAW12,
|
||||
}, {
|
||||
.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.fmt_val = CSI_WRDDR_TYPE_RGB888,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -132,6 +246,32 @@ static struct rkcif_sensor_info *get_active_sensor(struct rkcif_stream *stream)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned char get_data_type(u32 pixelformat, u8 cmd_mode_en)
|
||||
{
|
||||
switch (pixelformat) {
|
||||
/* csi raw8 */
|
||||
case V4L2_PIX_FMT_SRGGB8:
|
||||
case V4L2_PIX_FMT_SGRBG8:
|
||||
case V4L2_PIX_FMT_SGBRG8:
|
||||
case V4L2_PIX_FMT_SBGGR8:
|
||||
return 0x2a;
|
||||
/* csi raw10 */
|
||||
case V4L2_PIX_FMT_SRGGB10:
|
||||
case V4L2_PIX_FMT_SGRBG10:
|
||||
case V4L2_PIX_FMT_SGBRG10:
|
||||
case V4L2_PIX_FMT_SBGGR10:
|
||||
return 0x2b;
|
||||
case V4L2_PIX_FMT_RGB24: {
|
||||
if (cmd_mode_en) /* dsi command mode*/
|
||||
return 0x39;
|
||||
else /* dsi video mode */
|
||||
return 0x3e;
|
||||
}
|
||||
default:
|
||||
return 0x2b;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct
|
||||
cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd, struct v4l2_rect *rect)
|
||||
{
|
||||
@@ -221,11 +361,306 @@ static void rkcif_assign_new_buffer_oneframe(struct rkcif_stream *stream)
|
||||
}
|
||||
}
|
||||
|
||||
static void rkcif_assign_new_buffer_pingpong(struct rkcif_stream *stream,
|
||||
int init, int csi_ch)
|
||||
{
|
||||
struct rkcif_dummy_buffer *dummy_buf = &stream->dummy_buf;
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
struct rkcif_buffer *buffer = NULL;
|
||||
void __iomem *base = dev->base_addr;
|
||||
u32 frm_addr_y, frm_addr_uv;
|
||||
|
||||
/* Set up an empty buffer for the next frame */
|
||||
spin_lock(&stream->vbq_lock);
|
||||
if (!list_empty(&stream->buf_head)) {
|
||||
if (stream->frame_phase == 0 || init) {
|
||||
stream->curr_buf = list_first_entry(&stream->buf_head,
|
||||
struct rkcif_buffer, queue);
|
||||
list_del(&stream->curr_buf->queue);
|
||||
buffer = stream->curr_buf;
|
||||
}
|
||||
if (stream->frame_phase == 1 || init) {
|
||||
stream->next_buf = list_first_entry(&stream->buf_head,
|
||||
struct rkcif_buffer, queue);
|
||||
list_del(&stream->next_buf->queue);
|
||||
buffer = stream->next_buf;
|
||||
}
|
||||
} else {
|
||||
if (stream->frame_phase == 0)
|
||||
stream->curr_buf = NULL;
|
||||
if (stream->frame_phase == 1)
|
||||
stream->next_buf = NULL;
|
||||
|
||||
buffer = NULL;
|
||||
}
|
||||
spin_unlock(&stream->vbq_lock);
|
||||
|
||||
if (init) {
|
||||
u32 frm0_addr_y, frm0_addr_uv;
|
||||
u32 frm1_addr_y, frm1_addr_uv;
|
||||
|
||||
if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2) {
|
||||
frm0_addr_y = CIF_CSI_FRM0_ADDR_Y_ID0 + 0x20 * csi_ch;
|
||||
frm0_addr_uv = CIF_CSI_FRM0_ADDR_UV_ID0 + 0x20 * csi_ch;
|
||||
frm1_addr_y = CIF_CSI_FRM1_ADDR_Y_ID0 + 0x20 * csi_ch;
|
||||
frm1_addr_uv = CIF_CSI_FRM1_ADDR_UV_ID0 + 0x20 * csi_ch;
|
||||
} else {
|
||||
frm0_addr_y = CIF_FRM0_ADDR_Y;
|
||||
frm0_addr_uv = CIF_FRM0_ADDR_UV;
|
||||
frm1_addr_y = CIF_FRM1_ADDR_Y;
|
||||
frm1_addr_uv = CIF_FRM1_ADDR_UV;
|
||||
}
|
||||
|
||||
if (stream->curr_buf && stream->next_buf) {
|
||||
write_cif_reg(base, frm0_addr_y,
|
||||
stream->curr_buf->buff_addr[RKCIF_PLANE_Y]);
|
||||
write_cif_reg(base, frm0_addr_uv,
|
||||
stream->curr_buf->buff_addr[RKCIF_PLANE_CBCR]);
|
||||
write_cif_reg(base, frm1_addr_y,
|
||||
stream->next_buf->buff_addr[RKCIF_PLANE_Y]);
|
||||
write_cif_reg(base, frm1_addr_uv,
|
||||
stream->next_buf->buff_addr[RKCIF_PLANE_CBCR]);
|
||||
} else {
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "Drop to dummy buf\n");
|
||||
write_cif_reg(base, frm0_addr_y, dummy_buf->dma_addr);
|
||||
write_cif_reg(base, frm0_addr_uv, dummy_buf->dma_addr);
|
||||
write_cif_reg(base, frm1_addr_y, dummy_buf->dma_addr);
|
||||
write_cif_reg(base, frm1_addr_uv, dummy_buf->dma_addr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2) {
|
||||
frm_addr_y = stream->frame_phase == 1 ?
|
||||
(CIF_CSI_FRM1_ADDR_Y_ID0 + 0x20 * csi_ch) :
|
||||
(CIF_CSI_FRM0_ADDR_Y_ID0 + 0x20 * csi_ch);
|
||||
frm_addr_uv = stream->frame_phase == 1 ?
|
||||
(CIF_CSI_FRM1_ADDR_UV_ID0 + 0x20 * csi_ch) :
|
||||
(CIF_CSI_FRM0_ADDR_UV_ID0 + 0x20 * csi_ch);
|
||||
} else {
|
||||
frm_addr_y = stream->frame_phase == 1 ?
|
||||
CIF_FRM1_ADDR_Y : CIF_FRM0_ADDR_Y;
|
||||
frm_addr_uv = stream->frame_phase == 1 ?
|
||||
CIF_FRM1_ADDR_UV : CIF_FRM0_ADDR_UV;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
write_cif_reg(base, frm_addr_y,
|
||||
buffer->buff_addr[RKCIF_PLANE_Y]);
|
||||
write_cif_reg(base, frm_addr_uv,
|
||||
buffer->buff_addr[RKCIF_PLANE_CBCR]);
|
||||
} else {
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "Drop to dummy buf\n");
|
||||
write_cif_reg(base, frm_addr_y, dummy_buf->dma_addr);
|
||||
write_cif_reg(base, frm_addr_uv, dummy_buf->dma_addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void rkcif_csihost_disable(struct rkcif_device *dev)
|
||||
{
|
||||
void __iomem *base = dev->csi_base;
|
||||
|
||||
write_csihost_reg(base, CSIHOST_RESETN, 0);
|
||||
|
||||
v4l2_info(&dev->v4l2_dev, "mipi csi host disable\n");
|
||||
}
|
||||
|
||||
static void rkcif_csihost_enable(struct rkcif_device *dev,
|
||||
enum host_type_t host_type, int lanes)
|
||||
{
|
||||
void __iomem *base = dev->csi_base;
|
||||
|
||||
write_csihost_reg(base, CSIHOST_N_LANES, lanes - 1);
|
||||
|
||||
if (host_type == RK_DSI_RXHOST) {
|
||||
write_csihost_reg(base, CSIHOST_CONTROL,
|
||||
SW_CPHY_EN(0) | SW_DSI_EN(1) |
|
||||
SW_DATATYPE_FS(0x01) | SW_DATATYPE_FE(0x11) |
|
||||
SW_DATATYPE_LS(0x21) | SW_DATATYPE_LE(0x31));
|
||||
} else {
|
||||
write_csihost_reg(base, CSIHOST_CONTROL,
|
||||
SW_CPHY_EN(0) | SW_DSI_EN(0));
|
||||
}
|
||||
|
||||
write_csihost_reg(base, CSIHOST_RESETN, 1);
|
||||
|
||||
v4l2_info(&dev->v4l2_dev, "mipi csi host enable\n");
|
||||
}
|
||||
|
||||
static int rkcif_csi_crop_check(struct rkcif_device *dev,
|
||||
struct csi_channel_info *channel)
|
||||
{
|
||||
switch (channel->fmt_val) {
|
||||
case CSI_WRDDR_TYPE_RGB888:
|
||||
if (channel->crop_st_x % 24 != 0) {
|
||||
channel->crop_st_x = ALIGN(channel->crop_st_x, 24);
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"align 24 pixel: crop_st_x change to %d",
|
||||
channel->crop_st_x);
|
||||
}
|
||||
channel->width -= channel->crop_st_x / 3;
|
||||
break;
|
||||
case CSI_WRDDR_TYPE_RAW10:
|
||||
case CSI_WRDDR_TYPE_RAW12:
|
||||
if (channel->crop_st_x % 4 != 0) {
|
||||
channel->crop_st_x = ALIGN(channel->crop_st_x, 4);
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"align 4 pixel: crop_st_x change to %d",
|
||||
channel->crop_st_x);
|
||||
}
|
||||
channel->width -= channel->crop_st_x;
|
||||
break;
|
||||
case CSI_WRDDR_TYPE_RAW8:
|
||||
case CSI_WRDDR_TYPE_YUV422:
|
||||
if (channel->crop_st_x % 8 != 0) {
|
||||
channel->crop_st_x = ALIGN(channel->crop_st_x, 8);
|
||||
v4l2_info(&dev->v4l2_dev,
|
||||
"align 8 pixel: crop_st_x change to %d",
|
||||
channel->crop_st_x);
|
||||
}
|
||||
channel->width -= channel->crop_st_x;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
channel->height -= channel->crop_st_y;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rkcif_csi_channel_init(struct rkcif_stream *stream,
|
||||
struct csi_channel_info *channel)
|
||||
{
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
struct rkcif_sensor_info *sensor_info = dev->active_sensor;
|
||||
const struct cif_output_fmt *fmt;
|
||||
u32 mbus_flags = sensor_info->mbus.flags;
|
||||
|
||||
channel->enable = 1;
|
||||
channel->width = stream->pixm.width;
|
||||
channel->height = stream->pixm.height;
|
||||
channel->fmt_val = stream->cif_fmt_in->fmt_val;
|
||||
channel->cmd_mode_en = 0; /* default use DSI Video Mode */
|
||||
channel->crop_en = 1; /* Force crop enable to avoid write overflow */
|
||||
channel->crop_st_x = stream->crop.left;
|
||||
channel->crop_st_y = stream->crop.top;
|
||||
if (channel->crop_en)
|
||||
rkcif_csi_crop_check(dev, channel);
|
||||
|
||||
fmt = find_output_fmt(stream, stream->pixm.pixelformat);
|
||||
if (!fmt) {
|
||||
v4l2_err(&dev->v4l2_dev, "can not find output format: 0x%x",
|
||||
stream->pixm.pixelformat);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8);
|
||||
|
||||
/* TODO Modify data type !!!!!!!!!!!!!!! */
|
||||
channel->data_type =
|
||||
get_data_type(stream->pixm.pixelformat, channel->cmd_mode_en);
|
||||
|
||||
if (mbus_flags & V4L2_MBUS_CSI2_CHANNEL_0)
|
||||
channel->vc = 0;
|
||||
else if (mbus_flags & V4L2_MBUS_CSI2_CHANNEL_1)
|
||||
channel->vc = 1;
|
||||
else if (mbus_flags & V4L2_MBUS_CSI2_CHANNEL_2)
|
||||
channel->vc = 2;
|
||||
else if (mbus_flags & V4L2_MBUS_CSI2_CHANNEL_3)
|
||||
channel->vc = 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rkcif_csi_channel_set(struct rkcif_stream *stream,
|
||||
struct csi_channel_info *channel)
|
||||
{
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
void __iomem *base = dev->base_addr;
|
||||
unsigned int val;
|
||||
|
||||
if (channel->id >= 4)
|
||||
return -EINVAL;
|
||||
|
||||
if (!channel->enable) {
|
||||
write_cif_reg(base, CIF_CSI_ID0_CTRL0 + 0x8 * channel->id,
|
||||
CSI_DISABLE_CAPTURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_cif_reg(base, CIF_CSI_ID0_CTRL1 + 0x8 * channel->id,
|
||||
channel->width | (channel->height << 16));
|
||||
write_cif_reg(base, CIF_CSI_FRM0_VLW_Y_ID0 + 0x20 * channel->id,
|
||||
channel->virtual_width);
|
||||
write_cif_reg(base, CIF_CSI_FRM1_VLW_Y_ID0 + 0x20 * channel->id,
|
||||
channel->virtual_width);
|
||||
|
||||
if (channel->crop_en)
|
||||
write_cif_reg(base, CIF_CSI_ID0_CROP_START + 0x4 * channel->id,
|
||||
channel->crop_st_y << 16 | channel->crop_st_x);
|
||||
|
||||
/* Set up an buffer for the next frame */
|
||||
rkcif_assign_new_buffer_pingpong(stream, 1, channel->id);
|
||||
|
||||
val = CSI_ENABLE_CAPTURE | channel->fmt_val |
|
||||
channel->cmd_mode_en << 4 | channel->crop_en << 5 |
|
||||
channel->vc << 8 | channel->data_type << 10;
|
||||
write_cif_reg(base, CIF_CSI_ID0_CTRL0 + 0x8 * channel->id, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rkcif_csi_stream_start(struct rkcif_stream *stream)
|
||||
{
|
||||
struct rkcif_device *dev = stream->cifdev;
|
||||
struct rkcif_sensor_info *sensor_info = dev->active_sensor;
|
||||
void __iomem *base = dev->base_addr;
|
||||
enum host_type_t host_type;
|
||||
int i;
|
||||
|
||||
stream->frame_idx = 0;
|
||||
|
||||
/* TODO Modify to support multiple channel */
|
||||
for (i = 0; i < RKCIF_MAX_CSI_CHANNEL; i++) {
|
||||
struct csi_channel_info *channel = &dev->channels[i];
|
||||
|
||||
channel->id = i;
|
||||
|
||||
if (i < dev->num_channels)
|
||||
rkcif_csi_channel_init(stream, channel);
|
||||
else
|
||||
channel->enable = 0;
|
||||
|
||||
rkcif_csi_channel_set(stream, channel);
|
||||
}
|
||||
|
||||
write_cif_reg(base, CIF_CSI_INTSTAT, 0x0);
|
||||
write_cif_reg(base, CIF_CSI_INTEN,
|
||||
CSI_ALL_FRAME_START_INTEN |
|
||||
CSI_ALL_FRAME_END_INTEN |
|
||||
CSI_ALL_ERROR_INTEN);
|
||||
|
||||
/* enable csi host */
|
||||
if (stream->cif_fmt_in->mbus_code == MEDIA_BUS_FMT_RGB888_1X24)
|
||||
host_type = RK_DSI_RXHOST;
|
||||
else
|
||||
host_type = RK_CSI_RXHOST;
|
||||
|
||||
rkcif_csihost_enable(dev, host_type, sensor_info->lanes);
|
||||
|
||||
stream->state = RKCIF_STATE_STREAMING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rkcif_stream_stop(struct rkcif_stream *stream)
|
||||
{
|
||||
struct rkcif_device *cif_dev = stream->cifdev;
|
||||
void __iomem *base = cif_dev->base_addr;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
val = read_cif_reg(base, CIF_CTRL);
|
||||
write_cif_reg(base, CIF_CTRL, val & (~ENABLE_CAPTURE));
|
||||
@@ -233,6 +668,21 @@ static void rkcif_stream_stop(struct rkcif_stream *stream)
|
||||
write_cif_reg(base, CIF_INTSTAT, 0x3ff);
|
||||
write_cif_reg(base, CIF_FRAME_STATUS, 0x0);
|
||||
|
||||
if (cif_dev->active_sensor->mbus.type == V4L2_MBUS_CSI2) {
|
||||
/* disable csi host */
|
||||
rkcif_csihost_disable(cif_dev);
|
||||
|
||||
/* disable cif csi */
|
||||
for (i = 0; i < 4; i++) {
|
||||
val = read_cif_reg(base, CIF_CSI_ID0_CTRL0 + 0x8 * i);
|
||||
write_cif_reg(base, CIF_CSI_ID0_CTRL0 + 0x8 * i,
|
||||
(val & (~CSI_ENABLE_CAPTURE)));
|
||||
}
|
||||
|
||||
write_cif_reg(base, CIF_CSI_INTEN, 0x0);
|
||||
write_cif_reg(base, CIF_CSI_INTSTAT, 0x1ffffff);
|
||||
}
|
||||
|
||||
stream->state = RKCIF_STATE_READY;
|
||||
}
|
||||
|
||||
@@ -378,6 +828,11 @@ static void rkcif_stop_streaming(struct vb2_queue *queue)
|
||||
list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
|
||||
stream->curr_buf = NULL;
|
||||
}
|
||||
if (stream->next_buf) {
|
||||
list_add_tail(&stream->next_buf->queue, &stream->buf_head);
|
||||
stream->next_buf = NULL;
|
||||
}
|
||||
|
||||
while (!list_empty(&stream->buf_head)) {
|
||||
buf = list_first_entry(&stream->buf_head,
|
||||
struct rkcif_buffer, queue);
|
||||
@@ -536,7 +991,13 @@ static int rkcif_start_streaming(struct vb2_queue *queue, unsigned int count)
|
||||
v4l2_err(v4l2_dev, "Failed to get runtime pm, %d\n", ret);
|
||||
goto destroy_dummy_buf;
|
||||
}
|
||||
ret = rkcif_stream_start(stream);
|
||||
|
||||
if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2) {
|
||||
dev->num_channels = 1;
|
||||
ret = rkcif_csi_stream_start(stream);
|
||||
} else {
|
||||
ret = rkcif_stream_start(stream);
|
||||
}
|
||||
if (ret < 0)
|
||||
goto runtime_put;
|
||||
|
||||
@@ -844,7 +1305,7 @@ int rkcif_register_stream_vdev(struct rkcif_device *dev)
|
||||
struct video_device *vdev = &stream->vdev;
|
||||
int ret;
|
||||
|
||||
strlcpy(vdev->name, "stream_cif", sizeof(vdev->name));
|
||||
strlcpy(vdev->name, CIF_VIDEODEVICE_NAME, sizeof(vdev->name));
|
||||
mutex_init(&stream->vlock);
|
||||
|
||||
vdev->ioctl_ops = &rkcif_v4l2_ioctl_ops;
|
||||
@@ -968,5 +1429,80 @@ void rkcif_irq_oneframe(struct rkcif_device *cif_dev)
|
||||
|
||||
void rkcif_irq_pingpong(struct rkcif_device *cif_dev)
|
||||
{
|
||||
/* TODO */
|
||||
struct rkcif_stream *stream = &cif_dev->stream;
|
||||
void __iomem *base = cif_dev->base_addr;
|
||||
unsigned int intstat;
|
||||
|
||||
if (cif_dev->active_sensor->mbus.type == V4L2_MBUS_CSI2) {
|
||||
intstat = read_cif_reg(base, CIF_CSI_INTSTAT);
|
||||
/* clear all interrupts that has been triggered */
|
||||
write_cif_reg(base, CIF_CSI_INTSTAT, intstat);
|
||||
|
||||
if (intstat & CSI_FIFO_OVERFLOW) {
|
||||
v4l2_err(&cif_dev->v4l2_dev,
|
||||
"ERROR: csi fifo overflow!! intstat: 0x%x\n",
|
||||
intstat);
|
||||
return;
|
||||
}
|
||||
|
||||
if (intstat & CSI_BANDWIDTH_LACK) {
|
||||
v4l2_err(&cif_dev->v4l2_dev,
|
||||
"ERROR: csi bandwidth lack!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intstat & CSI_FRAME0_END_ID0 &&
|
||||
intstat & CSI_FRAME1_END_ID0) {
|
||||
v4l2_err(&cif_dev->v4l2_dev,
|
||||
"ERROR: both frame0 and frame1 int\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intstat & CSI_FRAME0_END_ID0 ||
|
||||
intstat & CSI_FRAME1_END_ID0) {
|
||||
struct vb2_v4l2_buffer *vb_done = NULL;
|
||||
|
||||
if (stream->stopping) {
|
||||
rkcif_stream_stop(stream);
|
||||
stream->stopping = false;
|
||||
wake_up(&stream->wq_stopped);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream->frame_idx == 0)
|
||||
stream->frame_phase =
|
||||
intstat & CSI_FRAME0_END_ID0 ? 0 : 1;
|
||||
else
|
||||
stream->frame_phase ^= 1;
|
||||
|
||||
if (intstat & CSI_FRAME0_END_ID0 &&
|
||||
stream->frame_phase != 0) {
|
||||
stream->frame_phase = 0;
|
||||
v4l2_err(&cif_dev->v4l2_dev,
|
||||
"ERROR: last frame1 intr miss\n");
|
||||
}
|
||||
if (intstat & CSI_FRAME1_END_ID0 &&
|
||||
stream->frame_phase != 1) {
|
||||
stream->frame_phase = 1;
|
||||
v4l2_err(&cif_dev->v4l2_dev,
|
||||
"ERROR: last frame0 intr miss\n");
|
||||
}
|
||||
|
||||
if (stream->frame_phase == 1) {
|
||||
if (stream->next_buf)
|
||||
vb_done = &stream->next_buf->vb;
|
||||
} else {
|
||||
if (stream->curr_buf)
|
||||
vb_done = &stream->curr_buf->vb;
|
||||
}
|
||||
rkcif_assign_new_buffer_pingpong(stream, 0, 0);
|
||||
|
||||
if (vb_done)
|
||||
rkcif_vb_done_oneframe(stream, vb_done);
|
||||
|
||||
stream->frame_idx++;
|
||||
}
|
||||
} else {
|
||||
/* TODO */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "regs.h"
|
||||
|
||||
struct cif_match_data {
|
||||
int chip_id;
|
||||
const char * const *clks;
|
||||
const char * const *rsts;
|
||||
int clks_num;
|
||||
@@ -96,6 +97,7 @@ unlock:
|
||||
struct rkcif_async_subdev {
|
||||
struct v4l2_async_subdev asd;
|
||||
struct v4l2_mbus_config mbus;
|
||||
int lanes;
|
||||
};
|
||||
|
||||
static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
|
||||
@@ -110,6 +112,7 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
|
||||
if (cif_dev->num_sensors == ARRAY_SIZE(cif_dev->sensors))
|
||||
return -EBUSY;
|
||||
|
||||
cif_dev->sensors[cif_dev->num_sensors].lanes = s_asd->lanes;
|
||||
cif_dev->sensors[cif_dev->num_sensors].mbus = s_asd->mbus;
|
||||
cif_dev->sensors[cif_dev->num_sensors].sd = subdev;
|
||||
++cif_dev->num_sensors;
|
||||
@@ -127,17 +130,20 @@ static int rkcif_fwnode_parse(struct device *dev,
|
||||
container_of(asd, struct rkcif_async_subdev, asd);
|
||||
struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel;
|
||||
|
||||
/*
|
||||
* MIPI sensor is linked with a mipi dphy and its media bus config can
|
||||
* not be get in here
|
||||
*/
|
||||
if (vep->bus_type != V4L2_MBUS_BT656 &&
|
||||
vep->bus_type != V4L2_MBUS_PARALLEL)
|
||||
vep->bus_type != V4L2_MBUS_PARALLEL &&
|
||||
vep->bus_type != V4L2_MBUS_CSI2)
|
||||
return 0;
|
||||
|
||||
rk_asd->mbus.flags = bus->flags;
|
||||
rk_asd->mbus.type = vep->bus_type;
|
||||
|
||||
if (vep->bus_type == V4L2_MBUS_CSI2) {
|
||||
rk_asd->mbus.flags = vep->bus.mipi_csi2.flags;
|
||||
rk_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
|
||||
} else {
|
||||
rk_asd->mbus.flags = bus->flags;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -199,6 +205,22 @@ static const char * const px30_cif_rsts[] = {
|
||||
"rst_cif_pclkin",
|
||||
};
|
||||
|
||||
static const char * const rk1808_cif_clks[] = {
|
||||
"aclk_cif",
|
||||
"dclk_cif",
|
||||
"hclk_cif",
|
||||
"sclk_cif_out",
|
||||
"pclk_csi2host"
|
||||
};
|
||||
|
||||
static const char * const rk1808_cif_rsts[] = {
|
||||
"rst_cif_a",
|
||||
"rst_cif_h",
|
||||
"rst_cif_i",
|
||||
"rst_cif_d",
|
||||
"rst_cif_pclkin",
|
||||
};
|
||||
|
||||
static const char * const rk3128_cif_clks[] = {
|
||||
"aclk_cif",
|
||||
"hclk_cif",
|
||||
@@ -220,21 +242,32 @@ static const char * const rk3288_cif_rsts[] = {
|
||||
"rst_cif",
|
||||
};
|
||||
|
||||
static const struct cif_match_data px30_cif_clk_data = {
|
||||
static const struct cif_match_data px30_cif_match_data = {
|
||||
.chip_id = CHIP_PX30_CIF,
|
||||
.clks = px30_cif_clks,
|
||||
.clks_num = ARRAY_SIZE(px30_cif_clks),
|
||||
.rsts = px30_cif_rsts,
|
||||
.rsts_num = ARRAY_SIZE(px30_cif_rsts),
|
||||
};
|
||||
|
||||
static const struct cif_match_data rk3128_cif_clk_data = {
|
||||
static const struct cif_match_data rk1808_cif_match_data = {
|
||||
.chip_id = CHIP_RK1808_CIF,
|
||||
.clks = rk1808_cif_clks,
|
||||
.clks_num = ARRAY_SIZE(rk1808_cif_clks),
|
||||
.rsts = rk1808_cif_rsts,
|
||||
.rsts_num = ARRAY_SIZE(rk1808_cif_rsts),
|
||||
};
|
||||
|
||||
static const struct cif_match_data rk3128_cif_match_data = {
|
||||
.chip_id = CHIP_RK3128_CIF,
|
||||
.clks = rk3128_cif_clks,
|
||||
.clks_num = ARRAY_SIZE(rk3128_cif_clks),
|
||||
.rsts = rk3128_cif_rsts,
|
||||
.rsts_num = ARRAY_SIZE(rk3128_cif_rsts),
|
||||
};
|
||||
|
||||
static const struct cif_match_data rk3288_cif_clk_data = {
|
||||
static const struct cif_match_data rk3288_cif_match_data = {
|
||||
.chip_id = CHIP_RK3288_CIF,
|
||||
.clks = rk3288_cif_clks,
|
||||
.clks_num = ARRAY_SIZE(rk3288_cif_clks),
|
||||
.rsts = rk3288_cif_rsts,
|
||||
@@ -244,15 +277,19 @@ static const struct cif_match_data rk3288_cif_clk_data = {
|
||||
static const struct of_device_id rkcif_plat_of_match[] = {
|
||||
{
|
||||
.compatible = "rockchip,px30-cif",
|
||||
.data = &px30_cif_clk_data,
|
||||
.data = &px30_cif_match_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk1808-cif",
|
||||
.data = &rk1808_cif_match_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3128-cif",
|
||||
.data = &rk3128_cif_clk_data,
|
||||
.data = &rk3128_cif_match_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3288-cif",
|
||||
.data = &rk3288_cif_clk_data,
|
||||
.data = &rk3288_cif_match_data,
|
||||
},
|
||||
{},
|
||||
};
|
||||
@@ -414,7 +451,7 @@ static int rkcif_plat_probe(struct platform_device *pdev)
|
||||
dev_set_drvdata(dev, cif_dev);
|
||||
cif_dev->dev = dev;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cif_regs");
|
||||
cif_dev->base_addr = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(cif_dev->base_addr))
|
||||
return PTR_ERR(cif_dev->base_addr);
|
||||
@@ -432,6 +469,17 @@ static int rkcif_plat_probe(struct platform_device *pdev)
|
||||
|
||||
cif_dev->irq = irq;
|
||||
data = match->data;
|
||||
cif_dev->chip_id = data->chip_id;
|
||||
if (data->chip_id == CHIP_RK1808_CIF) {
|
||||
using_pingpong = 1;
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csihost_regs");
|
||||
cif_dev->csi_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(cif_dev->csi_base))
|
||||
return PTR_ERR(cif_dev->csi_base);
|
||||
} else {
|
||||
using_pingpong = 0;
|
||||
}
|
||||
|
||||
if (data->clks_num > RKCIF_MAX_BUS_CLK ||
|
||||
data->rsts_num > RKCIF_MAX_RESET) {
|
||||
dev_err(dev, "out of range: clks(%d %d) rsts(%d %d)\n",
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
|
||||
#define CIF_DRIVER_NAME "rkcif"
|
||||
#define CIF_VIDEODEVICE_NAME "stream_cif"
|
||||
|
||||
#define RKCIF_MAX_BUS_CLK 8
|
||||
#define RKCIF_MAX_SENSOR 2
|
||||
#define RKCIF_MAX_RESET 3
|
||||
#define RKCIF_MAX_RESET 5
|
||||
#define RKCIF_MAX_CSI_CHANNEL 4
|
||||
|
||||
#define RKCIF_DEFAULT_WIDTH 640
|
||||
#define RKCIF_DEFAULT_HEIGHT 480
|
||||
@@ -27,12 +29,27 @@
|
||||
#define write_cif_reg(base, addr, val) writel(val, (addr) + (base))
|
||||
#define read_cif_reg(base, addr) readl((addr) + (base))
|
||||
|
||||
#define write_csihost_reg(base, addr, val) writel(val, (addr) + (base))
|
||||
#define read_csihost_reg(base, addr) readl((addr) + (base))
|
||||
|
||||
enum rkcif_state {
|
||||
RKCIF_STATE_DISABLED,
|
||||
RKCIF_STATE_READY,
|
||||
RKCIF_STATE_STREAMING
|
||||
};
|
||||
|
||||
enum rkcif_chip_id {
|
||||
CHIP_PX30_CIF,
|
||||
CHIP_RK1808_CIF,
|
||||
CHIP_RK3128_CIF,
|
||||
CHIP_RK3288_CIF
|
||||
};
|
||||
|
||||
enum host_type_t {
|
||||
RK_CSI_RXHOST,
|
||||
RK_DSI_RXHOST
|
||||
};
|
||||
|
||||
struct rkcif_buffer {
|
||||
struct vb2_v4l2_buffer vb;
|
||||
struct list_head queue;
|
||||
@@ -62,6 +79,7 @@ static inline struct rkcif_buffer *to_rkcif_buffer(struct vb2_v4l2_buffer *vb)
|
||||
struct rkcif_sensor_info {
|
||||
struct v4l2_subdev *sd;
|
||||
struct v4l2_mbus_config mbus;
|
||||
int lanes;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -97,6 +115,21 @@ struct cif_input_fmt {
|
||||
enum cif_fmt_type fmt_type;
|
||||
};
|
||||
|
||||
struct csi_channel_info {
|
||||
unsigned char id;
|
||||
unsigned char enable; /* capture enable */
|
||||
unsigned char vc;
|
||||
unsigned char data_type;
|
||||
unsigned char crop_en;
|
||||
unsigned char cmd_mode_en;
|
||||
unsigned char fmt_val;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int virtual_width;
|
||||
unsigned int crop_st_x;
|
||||
unsigned int crop_st_y;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct rkcif_stream - Stream states TODO
|
||||
*
|
||||
@@ -106,6 +139,7 @@ struct cif_input_fmt {
|
||||
*
|
||||
* rkcif use shadowsock registers, so it need two buffer at a time
|
||||
* @curr_buf: the buffer used for current frame
|
||||
* @next_buf: the buffer used for next frame
|
||||
*/
|
||||
struct rkcif_stream {
|
||||
struct rkcif_device *cifdev;
|
||||
@@ -113,6 +147,7 @@ struct rkcif_stream {
|
||||
bool stopping;
|
||||
wait_queue_head_t wq_stopped;
|
||||
int frame_idx;
|
||||
int frame_phase;
|
||||
|
||||
/* lock between irq and buf_queue */
|
||||
spinlock_t vbq_lock;
|
||||
@@ -120,6 +155,7 @@ struct rkcif_stream {
|
||||
struct list_head buf_head;
|
||||
struct rkcif_dummy_buffer dummy_buf;
|
||||
struct rkcif_buffer *curr_buf;
|
||||
struct rkcif_buffer *next_buf;
|
||||
|
||||
/* vfd lock */
|
||||
struct mutex vlock;
|
||||
@@ -148,6 +184,7 @@ struct rkcif_device {
|
||||
struct device *dev;
|
||||
int irq;
|
||||
void __iomem *base_addr;
|
||||
void __iomem *csi_base;
|
||||
struct clk *clks[RKCIF_MAX_BUS_CLK];
|
||||
int clk_size;
|
||||
struct vb2_alloc_ctx *alloc_ctx;
|
||||
@@ -165,6 +202,10 @@ struct rkcif_device {
|
||||
struct rkcif_sensor_info *active_sensor;
|
||||
|
||||
struct rkcif_stream stream;
|
||||
|
||||
struct csi_channel_info channels[RKCIF_MAX_CSI_CHANNEL];
|
||||
int num_channels;
|
||||
int chip_id;
|
||||
};
|
||||
|
||||
void rkcif_unregister_stream_vdev(struct rkcif_device *dev);
|
||||
|
||||
@@ -37,6 +37,59 @@
|
||||
#define CIF_LAST_LINE 0x68
|
||||
#define CIF_LAST_PIX 0x6c
|
||||
|
||||
/* RK1808 CIF CSI Registers Offset */
|
||||
#define CIF_CSI_ID0_CTRL0 0x80
|
||||
#define CIF_CSI_ID0_CTRL1 0x84
|
||||
#define CIF_CSI_ID1_CTRL0 0x88
|
||||
#define CIF_CSI_ID1_CTRL1 0x8c
|
||||
#define CIF_CSI_ID2_CTRL0 0x90
|
||||
#define CIF_CSI_ID2_CTRL1 0x94
|
||||
#define CIF_CSI_ID3_CTRL0 0x98
|
||||
#define CIF_CSI_ID3_CTRL1 0x9c
|
||||
#define CIF_CSI_WATER_LINE 0xa0
|
||||
#define CIF_CSI_FRM0_ADDR_Y_ID0 0xa4
|
||||
#define CIF_CSI_FRM1_ADDR_Y_ID0 0xa8
|
||||
#define CIF_CSI_FRM0_ADDR_UV_ID0 0xac
|
||||
#define CIF_CSI_FRM1_ADDR_UV_ID0 0xb0
|
||||
#define CIF_CSI_FRM0_VLW_Y_ID0 0xb4
|
||||
#define CIF_CSI_FRM1_VLW_Y_ID0 0xb8
|
||||
#define CIF_CSI_FRM0_VLW_UV_ID0 0xbc
|
||||
#define CIF_CSI_FRM1_VLW_UV_ID0 0xc0
|
||||
#define CIF_CSI_FRM0_ADDR_Y_ID1 0xc4
|
||||
#define CIF_CSI_FRM1_ADDR_Y_ID1 0xc8
|
||||
#define CIF_CSI_FRM0_ADDR_UV_ID1 0xcc
|
||||
#define CIF_CSI_FRM1_ADDR_UV_ID1 0xd0
|
||||
#define CIF_CSI_FRM0_VLW_Y_ID1 0xd4
|
||||
#define CIF_CSI_FRM1_VLW_Y_ID1 0xd8
|
||||
#define CIF_CSI_FRM0_VLW_UV_ID1 0xdc
|
||||
#define CIF_CSI_FRM1_VLW_UV_ID1 0xe0
|
||||
#define CIF_CSI_FRM0_ADDR_Y_ID2 0xe4
|
||||
#define CIF_CSI_FRM1_ADDR_Y_ID2 0xe8
|
||||
#define CIF_CSI_FRM0_ADDR_UV_ID2 0xec
|
||||
#define CIF_CSI_FRM1_ADDR_UV_ID2 0xf0
|
||||
#define CIF_CSI_FRM0_VLW_Y_ID2 0xf4
|
||||
#define CIF_CSI_FRM1_VLW_Y_ID2 0xf8
|
||||
#define CIF_CSI_FRM0_VLW_UV_ID2 0xfc
|
||||
#define CIF_CSI_FRM1_VLW_UV_ID2 0x100
|
||||
#define CIF_CSI_FRM0_ADDR_Y_ID3 0x104
|
||||
#define CIF_CSI_FRM1_ADDR_Y_ID3 0x108
|
||||
#define CIF_CSI_FRM0_ADDR_UV_ID3 0x10c
|
||||
#define CIF_CSI_FRM1_ADDR_UV_ID3 0x110
|
||||
#define CIF_CSI_FRM0_VLW_Y_ID3 0x114
|
||||
#define CIF_CSI_FRM1_VLW_Y_ID3 0x118
|
||||
#define CIF_CSI_FRM0_VLW_UV_ID3 0x11c
|
||||
#define CIF_CSI_FRM1_VLW_UV_ID3 0x120
|
||||
#define CIF_CSI_INTEN 0x124
|
||||
#define CIF_CSI_INTSTAT 0x128
|
||||
#define CIF_CSI_LINE_INT_NUM_ID0_1 0x12c
|
||||
#define CIF_CSI_LINE_INT_NUM_ID2_3 0x130
|
||||
#define CIF_CSI_LINE_CNT_ID0_1 0x134
|
||||
#define CIF_CSI_LINE_CNT_ID2_3 0x138
|
||||
#define CIF_CSI_ID0_CROP_START 0x13c
|
||||
#define CIF_CSI_ID1_CROP_START 0x140
|
||||
#define CIF_CSI_ID2_CROP_START 0x144
|
||||
#define CIF_CSI_ID3_CROP_START 0x148
|
||||
|
||||
/* The key register bit description */
|
||||
|
||||
/* CIF_CTRL Reg */
|
||||
@@ -119,4 +172,72 @@
|
||||
#define CIF_CROP_Y_SHIFT 16
|
||||
#define CIF_CROP_X_SHIFT 0
|
||||
|
||||
/* CIF_CSI_ID_CTRL0 */
|
||||
#define CSI_DISABLE_CAPTURE (0x0 << 0)
|
||||
#define CSI_ENABLE_CAPTURE (0x1 << 0)
|
||||
#define CSI_WRDDR_TYPE_RAW8 (0x0 << 1)
|
||||
#define CSI_WRDDR_TYPE_RAW10 (0x1 << 1)
|
||||
#define CSI_WRDDR_TYPE_RAW12 (0x2 << 1)
|
||||
#define CSI_WRDDR_TYPE_RGB888 (0x3 << 1)
|
||||
#define CSI_WRDDR_TYPE_YUV422 (0x4 << 1)
|
||||
#define CSI_DISABLE_COMMAND_MODE (0x0 << 4)
|
||||
#define CSI_ENABLE_COMMAND_MODE (0x1 << 4)
|
||||
#define CSI_DISABLE_CROP (0x0 << 5)
|
||||
#define CSI_ENABLE_CROP (0x1 << 5)
|
||||
|
||||
/* CIF_CSI_INTEN */
|
||||
#define CSI_FRAME0_START_INTEN(id) (0x1 << ((id) * 2))
|
||||
#define CSI_FRAME1_START_INTEN(id) (0x1 << ((id) * 2 + 1))
|
||||
#define CSI_FRAME0_END_INTEN(id) (0x1 << ((id) * 2 + 8))
|
||||
#define CSI_FRAME1_END_INTEN(id) (0x1 << ((id) * 2 + 9))
|
||||
#define CSI_DMA_Y_FIFO_OVERFLOW_INTEN (0x1 << 16)
|
||||
#define CSI_DMA_UV_FIFO_OVERFLOW_INTEN (0x1 << 17)
|
||||
#define CSI_CONFIG_FIFO_OVERFLOW_INTEN (0x1 << 18)
|
||||
#define CSI_BANDWIDTH_LACK_INTEN (0x1 << 19)
|
||||
#define CSI_RX_FIFO_OVERFLOW_INTEN (0x1 << 20)
|
||||
#define CSI_ALL_FRAME_START_INTEN (0xff << 0)
|
||||
#define CSI_ALL_FRAME_END_INTEN (0xff << 8)
|
||||
#define CSI_ALL_ERROR_INTEN (0x1f << 16)
|
||||
|
||||
/* CIF_CSI_INTSTAT */
|
||||
#define CSI_FRAME0_START_ID0 (0x1 << 0)
|
||||
#define CSI_FRAME1_START_ID0 (0x1 << 1)
|
||||
#define CSI_FRAME0_START_ID1 (0x1 << 2)
|
||||
#define CSI_FRAME1_START_ID1 (0x1 << 3)
|
||||
#define CSI_FRAME0_START_ID2 (0x1 << 4)
|
||||
#define CSI_FRAME1_START_ID2 (0x1 << 5)
|
||||
#define CSI_FRAME0_START_ID3 (0x1 << 6)
|
||||
#define CSI_FRAME1_START_ID3 (0x1 << 7)
|
||||
#define CSI_FRAME0_END_ID0 (0x1 << 8)
|
||||
#define CSI_FRAME1_END_ID0 (0x1 << 9)
|
||||
#define CSI_FRAME0_END_ID1 (0x1 << 10)
|
||||
#define CSI_FRAME1_END_ID1 (0x1 << 11)
|
||||
#define CSI_FRAME0_END_ID2 (0x1 << 12)
|
||||
#define CSI_FRAME1_END_ID2 (0x1 << 13)
|
||||
#define CSI_FRAME0_END_ID3 (0x1 << 14)
|
||||
#define CSI_FRAME1_END_ID3 (0x1 << 15)
|
||||
#define CSI_DMA_Y_FIFO_OVERFLOW (0x1 << 16)
|
||||
#define CSI_DMA_UV_FIFO_OVERFLOW (0x1 << 17)
|
||||
#define CSI_CONFIG_FIFO_OVERFLOW (0x1 << 18)
|
||||
#define CSI_BANDWIDTH_LACK (0x1 << 19)
|
||||
#define CSI_RX_FIFO_OVERFLOW (0x1 << 20)
|
||||
|
||||
#define CSI_FIFO_OVERFLOW (CSI_DMA_Y_FIFO_OVERFLOW | \
|
||||
CSI_DMA_UV_FIFO_OVERFLOW | \
|
||||
CSI_CONFIG_FIFO_OVERFLOW | \
|
||||
CSI_RX_FIFO_OVERFLOW)
|
||||
|
||||
/* CSI Host Registers Define */
|
||||
#define CSIHOST_N_LANES 0x04
|
||||
#define CSIHOST_PHY_RSTZ 0x0c
|
||||
#define CSIHOST_RESETN 0x10
|
||||
#define CSIHOST_CONTROL 0x40
|
||||
|
||||
#define SW_CPHY_EN(x) ((x) << 0)
|
||||
#define SW_DSI_EN(x) ((x) << 4)
|
||||
#define SW_DATATYPE_FS(x) ((x) << 8)
|
||||
#define SW_DATATYPE_FE(x) ((x) << 14)
|
||||
#define SW_DATATYPE_LS(x) ((x) << 20)
|
||||
#define SW_DATATYPE_LE(x) ((x) << 26)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user