media: rockchip: vicap support rk3576

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: Ib8b9f4cb13df750712459383fc643ada6c43734d
This commit is contained in:
Zefa Chen
2023-05-08 20:38:28 +08:00
committed by Tao Huang
parent a57197e5ab
commit 3d5034018f
11 changed files with 1307 additions and 180 deletions

View File

@@ -351,6 +351,7 @@ static const struct cif_output_fmt out_fmts[] = {
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG16,
@@ -358,6 +359,7 @@ static const struct cif_output_fmt out_fmts[] = {
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG16,
@@ -365,6 +367,7 @@ static const struct cif_output_fmt out_fmts[] = {
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR16,
@@ -372,6 +375,7 @@ static const struct cif_output_fmt out_fmts[] = {
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW16,
.fmt_type = CIF_FMT_TYPE_RAW,
}
/* TODO: We can support NV12M/NV21M/NV16M/NV61M too */
@@ -506,6 +510,26 @@ static const struct cif_input_fmt in_fmts[] = {
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SBGGR14_1X14,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGBRG14_1X14,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGRBG14_1X14,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SRGGB14_1X14,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW14_RK3588,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
.csi_fmt_val = CSI_WRDDR_TYPE_RGB888,
@@ -552,7 +576,37 @@ static const struct cif_input_fmt in_fmts[] = {
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}
}, {
.mbus_code = MEDIA_BUS_FMT_YUV8_1X24,//use for yuv420_8bit input
.csi_fmt_val = CSI_WRDDR_TYPE_YUV420SP,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_UV8_1X8,//use for yuv420_8bit legacy input
.csi_fmt_val = CSI_WRDDR_TYPE_YUV420LEGACY,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SBGGR16_1X16,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW16,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGBRG16_1X16,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW16,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGRBG16_1X16,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW16,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SRGGB16_1X16,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW16,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
},
};
static inline int rkcif_get_interlace_mode(struct rkcif_stream *stream)
@@ -685,6 +739,16 @@ static int rkcif_output_fmt_check(struct rkcif_stream *stream,
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR16)))
ret = 0;
break;
case MEDIA_BUS_FMT_SBGGR16_1X16:
case MEDIA_BUS_FMT_SGBRG16_1X16:
case MEDIA_BUS_FMT_SGRBG16_1X16:
case MEDIA_BUS_FMT_SRGGB16_1X16:
if (output_fmt->fourcc == V4L2_PIX_FMT_SRGGB16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGRBG16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SGBRG16 ||
output_fmt->fourcc == V4L2_PIX_FMT_SBGGR16)
ret = 0;
break;
default:
break;
}
@@ -811,6 +875,12 @@ static unsigned char get_data_type(u32 pixelformat, u8 cmd_mode_en, u8 dsi_input
case MEDIA_BUS_FMT_SRGGB12_1X12:
case MEDIA_BUS_FMT_Y12_1X12:
return 0x2c;
/* csi raw16 */
case MEDIA_BUS_FMT_SBGGR16_1X16:
case MEDIA_BUS_FMT_SGBRG16_1X16:
case MEDIA_BUS_FMT_SGRBG16_1X16:
case MEDIA_BUS_FMT_SRGGB16_1X16:
return 0x2e;
/* csi uyvy 422 */
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
@@ -1682,9 +1752,16 @@ static void rkcif_enable_skip_frame(struct rkcif_stream *stream, int cap_m, int
u32 val = 0;
val = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_CTRL);
val &= 0xc00fffff;
val |= cap_m << RKCIF_CAP_SHIFT | skip_n << RKCIF_SKIP_SHIFT | RKCIF_SKIP_EN(stream->id);
if (dev->chip_id > CHIP_RK3562_CIF) {
val &= 0xc00fffff;
val |= cap_m << RKCIF_CAP_SHIFT_RK3576 | skip_n << RKCIF_SKIP_SHIFT_RK3576;
} else {
val &= 0xffff00ff;
val |= cap_m << RKCIF_CAP_SHIFT | skip_n << RKCIF_SKIP_SHIFT | RKCIF_SKIP_EN(stream->id);
}
rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val);
if (dev->chip_id > CHIP_RK3562_CIF)
rkcif_write_register_or(dev, get_reg_index_of_id_ctrl0(stream->id), RKCIF_SKIP_EN_RK3576);
stream->skip_info.skip_en = true;
}
@@ -1692,9 +1769,14 @@ static void rkcif_disable_skip_frame(struct rkcif_stream *stream)
{ struct rkcif_device *dev = stream->cifdev;
u32 val = 0;
val = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_CTRL);
val &= ~(RKCIF_SKIP_EN(stream->id));
rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val);
if (dev->chip_id > CHIP_RK3562_CIF) {
rkcif_write_register_and(dev, get_reg_index_of_id_ctrl0(stream->id),
~RKCIF_SKIP_EN_RK3576);
} else {
val = rkcif_read_register(dev, CIF_REG_MIPI_LVDS_CTRL);
val &= ~(RKCIF_SKIP_EN(stream->id));
rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val);
}
stream->skip_info.skip_en = false;
}
@@ -3492,6 +3574,8 @@ static int rkcif_csi_channel_init(struct rkcif_stream *stream,
channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8);
}
}
if (dev->chip_id > CHIP_RK3562_CIF && stream->sw_dbg_en)
channel->virtual_width = (channel->virtual_width + 23) / 24 * 24;
if (channel->fmt_val == CSI_WRDDR_TYPE_RGB888 || channel->fmt_val == CSI_WRDDR_TYPE_RGB565)
channel->width = channel->width * fmt->bpp[0] / 8;
@@ -3831,6 +3915,76 @@ static int rkcif_csi_get_output_type_mask(struct rkcif_stream *stream)
return mask;
}
static int rkcif_csi_get_output_type_mask_rk3576(struct rkcif_stream *stream)
{
unsigned int mask;
const struct cif_output_fmt *fmt = stream->cif_fmt_out;
switch (fmt->fourcc) {
case V4L2_PIX_FMT_NV16:
mask = CSI_WRDDR_TYPE_YUV422SP_RK3588 << 3 | CSI_YUV_OUTPUT_ORDER_UYVY >> 4;
break;
case V4L2_PIX_FMT_NV61:
mask = CSI_WRDDR_TYPE_YUV422SP_RK3588 << 3 | CSI_YUV_OUTPUT_ORDER_VYUY >> 4;
break;
case V4L2_PIX_FMT_NV12:
mask = CSI_WRDDR_TYPE_YUV420SP_RK3588 << 3 | CSI_YUV_OUTPUT_ORDER_UYVY >> 4;
break;
case V4L2_PIX_FMT_NV21:
mask = CSI_WRDDR_TYPE_YUV420SP_RK3588 << 3 | CSI_YUV_OUTPUT_ORDER_VYUY >> 4;
break;
case V4L2_PIX_FMT_YUYV:
mask = CSI_WRDDR_TYPE_YUV_PACKET << 3 | CSI_YUV_OUTPUT_ORDER_YUYV >> 4;
break;
case V4L2_PIX_FMT_YVYU:
mask = CSI_WRDDR_TYPE_YUV_PACKET << 3 | CSI_YUV_OUTPUT_ORDER_YVYU >> 4;
break;
case V4L2_PIX_FMT_UYVY:
mask = CSI_WRDDR_TYPE_YUV_PACKET << 3 | CSI_YUV_OUTPUT_ORDER_UYVY >> 4;
break;
case V4L2_PIX_FMT_VYUY:
mask = CSI_WRDDR_TYPE_YUV_PACKET << 3 | CSI_YUV_OUTPUT_ORDER_VYUY >> 4;
break;
case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_BGR666:
mask = CSI_WRDDR_TYPE_RAW_COMPACT << 3;
break;
case V4L2_PIX_FMT_SRGGB8:
case V4L2_PIX_FMT_SGRBG8:
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SBGGR8:
case V4L2_PIX_FMT_SRGGB10:
case V4L2_PIX_FMT_SGRBG10:
case V4L2_PIX_FMT_SGBRG10:
case V4L2_PIX_FMT_SBGGR10:
case V4L2_PIX_FMT_SRGGB12:
case V4L2_PIX_FMT_SGRBG12:
case V4L2_PIX_FMT_SGBRG12:
case V4L2_PIX_FMT_SBGGR12:
case V4L2_PIX_FMT_GREY:
case V4L2_PIX_FMT_Y10:
case V4L2_PIX_FMT_Y12:
if (stream->is_compact)
mask = CSI_WRDDR_TYPE_RAW_COMPACT << 3;
else
mask = CSI_WRDDR_TYPE_RAW_UNCOMPACT << 3;
break;
case V4L2_PIX_FMT_SBGGR16:
case V4L2_PIX_FMT_SGBRG16:
case V4L2_PIX_FMT_SGRBG16:
case V4L2_PIX_FMT_SRGGB16:
case V4L2_PIX_FMT_Y16:
mask = CSI_WRDDR_TYPE_RAW_UNCOMPACT << 3;
break;
default:
mask = CSI_WRDDR_TYPE_RAW_COMPACT << 3;
break;
}
return mask;
}
static int rkcif_lvds_get_output_type_mask(struct rkcif_stream *stream)
{
unsigned int mask;
@@ -3929,6 +4083,47 @@ static void rkcif_modify_frame_skip_config(struct rkcif_stream *stream)
}
}
static u32 rkcif_get_parse_type_rk3576(const struct cif_input_fmt *cif_fmt_in)
{
u32 parse_type = 0;
switch (cif_fmt_in->csi_fmt_val) {
case CSI_WRDDR_TYPE_RAW8:
parse_type = CSI_WRDDR_TYPE_RAW8 << 3;
break;
case CSI_WRDDR_TYPE_RAW10:
parse_type = CSI_WRDDR_TYPE_RAW10 << 3;
break;
case CSI_WRDDR_TYPE_RAW12:
parse_type = CSI_WRDDR_TYPE_RAW12 << 3;
break;
case CSI_WRDDR_TYPE_RAW14_RK3588:
parse_type = CSI_WRDDR_TYPE_RAW14_RK3588 << 4;
break;
case CSI_WRDDR_TYPE_RGB888:
parse_type = CSI_WRDDR_TYPE_RGB888_RK3576;
break;
case CSI_WRDDR_TYPE_YUV422:
if (cif_fmt_in->field == V4L2_FIELD_NONE)
parse_type = CSI_WRDDR_TYPE_YUV422 << 4;
else
parse_type = (CSI_WRDDR_TYPE_YUV422 + 1) << 4;
break;
case CSI_WRDDR_TYPE_YUV420SP:
parse_type = CSI_WRDDR_TYPE_YUV420SP << 4;
break;
case CSI_WRDDR_TYPE_YUV420LEGACY:
parse_type = CSI_WRDDR_TYPE_YUV420LEGACY;
break;
case CSI_WRDDR_TYPE_RAW16:
parse_type = CSI_WRDDR_TYPE_RAW16;
break;
default:
break;
}
return parse_type;
}
/*config reg for rk3588*/
static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
struct csi_channel_info *channel,
@@ -3953,6 +4148,19 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
return 0;
}
if (stream->sw_dbg_en) {
rkcif_write_register_and(dev, CIF_REG_GLB_CTRL,
~(u32)BIT(16));
v4l2_subdev_call(dev->active_sensor->sd,
core, ioctl,
RKCIF_CMD_SET_PPI_DATA_DEBUG,
&stream->sw_dbg_en);
} else {
v4l2_subdev_call(dev->active_sensor->sd,
core, ioctl,
RKCIF_CMD_SET_PPI_DATA_DEBUG,
&stream->sw_dbg_en);
}
rkcif_write_register_and(dev, CIF_REG_MIPI_LVDS_INTSTAT,
~(CSI_START_INTSTAT(channel->id) |
CSI_DMA_END_INTSTAT(channel->id) |
@@ -3962,7 +4170,9 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
index < capture_info->multi_dev.dev_num - 1)) {
rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
CSI_START_INTEN(channel->id));
dev->chip_id < CHIP_RK3576_CIF ?
CSI_START_INTEN(channel->id) :
CSI_START_INTEN_RK3576(channel->id));
if (priv && priv->mode.rdbk_mode && detect_stream->is_line_wake_up) {
rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
@@ -3976,28 +4186,39 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
CSI_DMA_END_INTEN(channel->id));
}
if (stream->cifdev->id_use_cnt == 0) {
if (dev->chip_id > CHIP_RK3562_CIF) {
val = CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE |
(CIF_MIPI_LVDS_SW_WATER_LINE_25 << 19);
if (stream->cifdev->hdr.hdr_mode != NO_HDR &&
stream->cifdev->hdr.esp.mode == HDR_NORMAL_VC)
val |= CSI_HDR_VC_MODE_PROTECT >> 25;
val |= (!!stream->sw_dbg_en) << 31;
rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val);
} else {
val = CIF_MIPI_LVDS_SW_PRESS_VALUE_RK3588(0x3) |
CIF_MIPI_LVDS_SW_PRESS_ENABLE |
CIF_MIPI_LVDS_SW_HURRY_VALUE_RK3588(0x3) |
CIF_MIPI_LVDS_SW_HURRY_ENABLE |
CIF_MIPI_LVDS_SW_WATER_LINE_25 |
CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE;
if (mbus_type == V4L2_MBUS_CSI2_DPHY ||
mbus_type == V4L2_MBUS_CSI2_CPHY)
val &= ~CIF_MIPI_LVDS_SW_SEL_LVDS_RV1106;
else
val |= CIF_MIPI_LVDS_SW_SEL_LVDS_RV1106;
rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val);
}
rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_INTEN,
CSI_ALL_ERROR_INTEN_V1);
}
if (stream->cifdev->id_use_cnt == 0) {
val = CIF_MIPI_LVDS_SW_PRESS_VALUE_RK3588(0x3) |
CIF_MIPI_LVDS_SW_PRESS_ENABLE |
CIF_MIPI_LVDS_SW_HURRY_VALUE_RK3588(0x3) |
CIF_MIPI_LVDS_SW_HURRY_ENABLE |
CIF_MIPI_LVDS_SW_WATER_LINE_25 |
CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE;
if (mbus_type == V4L2_MBUS_CSI2_DPHY ||
mbus_type == V4L2_MBUS_CSI2_CPHY)
val &= ~CIF_MIPI_LVDS_SW_SEL_LVDS_RV1106;
else
val |= CIF_MIPI_LVDS_SW_SEL_LVDS_RV1106;
rkcif_write_register(dev, CIF_REG_MIPI_LVDS_CTRL, val);
}
#if IS_ENABLED(CONFIG_CPU_RV1106)
if (channel->id == 1)
rv1106_sdmmc_get_lock();
#endif
if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
priv && priv->mode.rdbk_mode == RKISP_VICAP_ONLINE &&
(dev->hdr.hdr_mode == NO_HDR ||
@@ -4005,8 +4226,12 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
(dev->hdr.hdr_mode == HDR_X3 && stream->id == 2)))
offset = channel->capture_info.multi_dev.pixel_offset;
rkcif_write_register(dev, get_reg_index_of_id_ctrl1(channel->id),
(channel->width + offset) | (channel->height << 16));
if (dev->chip_id < CHIP_RK3576_CIF)
rkcif_write_register(dev, get_reg_index_of_id_ctrl1(channel->id),
(channel->width + offset) | (channel->height << 16));
else
rkcif_write_register(dev, CIF_REG_MIPI_SET_SIZE_ID0 + channel->id,
(channel->width + offset) | (channel->height << 16));
#if IS_ENABLED(CONFIG_CPU_RV1106)
if (channel->id == 1)
@@ -4050,10 +4275,14 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
if (stream->dma_en) {
if (mbus_type == V4L2_MBUS_CSI2_DPHY ||
mbus_type == V4L2_MBUS_CSI2_CPHY)
dma_en = CSI_DMA_ENABLE;
else
mbus_type == V4L2_MBUS_CSI2_CPHY) {
if (dev->chip_id > CHIP_RK3562_CIF)
dma_en = CSI_DMA_ENABLE_RK3576;
else
dma_en = CSI_DMA_ENABLE;
} else {
dma_en = LVDS_DMAEN_RV1106;
}
}
if (mbus_type == V4L2_MBUS_CSI2_DPHY ||
mbus_type == V4L2_MBUS_CSI2_CPHY) {
@@ -4062,34 +4291,80 @@ static int rkcif_csi_channel_set_v1(struct rkcif_stream *stream,
stream->cifdev->hdr.esp.mode == HDR_ID_CODE)
channel->vc = 0;
val = CSI_ENABLE_CAPTURE | dma_en |
channel->cmd_mode_en << 26 | CSI_ENABLE_CROP_V1 |
channel->vc << 8 | channel->data_type << 10 |
channel->csi_fmt_val;
if (dev->chip_id > CHIP_RK3562_CIF) {
val = CSI_ENABLE_CAPTURE | dma_en |
CSI_ENABLE_CROP_RK3576;
val |= rkcif_get_parse_type_rk3576(stream->cif_fmt_in);
val |= rkcif_csi_get_output_type_mask_rk3576(stream);
val |= stream->cif_fmt_in->csi_yuv_order >> 4;
if (stream->is_high_align)
val |= CSI_HIGH_ALIGN_RK3576;
else
val &= ~CSI_HIGH_ALIGN_RK3576;
if (stream->id == 0 && (stream->cif_fmt_out->fourcc == V4L2_PIX_FMT_NV12 ||
stream->cif_fmt_out->fourcc == V4L2_PIX_FMT_NV21))
val |= CSI_UVDS_EN;
rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val);
val |= stream->cif_fmt_in->csi_yuv_order;
val |= rkcif_csi_get_output_type_mask(stream);
if (stream->cifdev->hdr.hdr_mode == NO_HDR ||
stream->cifdev->hdr.hdr_mode == HDR_COMPR)
val |= CSI_NO_HDR;
else if (stream->cifdev->hdr.hdr_mode == HDR_X2)
val |= CSI_HDR2;
else if (stream->cifdev->hdr.hdr_mode == HDR_X3)
val |= CSI_HDR3;
if (stream->cifdev->hdr.esp.mode == HDR_NORMAL_VC)
val |= CSI_HDR_MODE_VC;
else if (stream->cifdev->hdr.esp.mode == HDR_LINE_CNT)
val |= CSI_HDR_MODE_LINE_CNT;
else if (stream->cifdev->hdr.esp.mode == HDR_ID_CODE)
val |= CSI_HDR_MODE_LINE_INFO;
if (stream->cifdev->hdr.hdr_mode != NO_HDR &&
stream->cifdev->hdr.esp.mode == HDR_NORMAL_VC)
val |= CSI_HDR_VC_MODE_PROTECT;
if (stream->is_high_align)
val |= CSI_HIGH_ALIGN_RK3588;
else
val &= ~CSI_HIGH_ALIGN_RK3588;
rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val);
val = channel->vc | channel->data_type << 2;
if (stream->cifdev->hdr.hdr_mode == NO_HDR ||
stream->cifdev->hdr.hdr_mode == HDR_COMPR)
val |= CSI_NO_HDR >> 12;
else if (stream->cifdev->hdr.hdr_mode == HDR_X2)
val |= CSI_HDR2 >> 12;
else if (stream->cifdev->hdr.hdr_mode == HDR_X3)
val |= CSI_HDR3 >> 12;
if (stream->cifdev->hdr.esp.mode == HDR_NORMAL_VC) {
val |= CSI_HDR_MODE_VC >> 12;
} else if (stream->cifdev->hdr.esp.mode == HDR_LINE_CNT) {
val |= CSI_HDR_MODE_LINE_CNT >> 12;
rkcif_write_register(dev, CIF_REG_MIPI_ON_PAD, 0x4);
val |= stream->id << 12;
} else if (stream->cifdev->hdr.esp.mode == HDR_ID_CODE) {
val |= CSI_HDR_MODE_LINE_INFO >> 12;
}
val |= channel->cmd_mode_en << 14;
rkcif_write_register(dev, get_reg_index_of_id_ctrl1(channel->id), val);
} else {
val = CSI_ENABLE_CAPTURE | dma_en |
channel->cmd_mode_en << 26 | CSI_ENABLE_CROP_V1 |
channel->vc << 8 | channel->data_type << 10;
if (dev->chip_id >= CHIP_RK3588_CIF) {
if (channel->csi_fmt_val == CSI_WRDDR_TYPE_RGB888)
val |= CSI_WRDDR_TYPE_RAW8;
else if (channel->csi_fmt_val == CSI_WRDDR_TYPE_RAW14_RK3588)
val |= channel->csi_fmt_val << 1;
else
val |= channel->csi_fmt_val;
} else {
val |= channel->csi_fmt_val;
}
val |= stream->cif_fmt_in->csi_yuv_order;
val |= rkcif_csi_get_output_type_mask(stream);
if (stream->cifdev->hdr.hdr_mode == NO_HDR ||
stream->cifdev->hdr.hdr_mode == HDR_COMPR)
val |= CSI_NO_HDR;
else if (stream->cifdev->hdr.hdr_mode == HDR_X2)
val |= CSI_HDR2;
else if (stream->cifdev->hdr.hdr_mode == HDR_X3)
val |= CSI_HDR3;
if (stream->cifdev->hdr.esp.mode == HDR_NORMAL_VC)
val |= CSI_HDR_MODE_VC;
else if (stream->cifdev->hdr.esp.mode == HDR_LINE_CNT)
val |= CSI_HDR_MODE_LINE_CNT;
else if (stream->cifdev->hdr.esp.mode == HDR_ID_CODE)
val |= CSI_HDR_MODE_LINE_INFO;
if (stream->cifdev->hdr.hdr_mode != NO_HDR &&
stream->cifdev->hdr.esp.mode == HDR_NORMAL_VC)
val |= CSI_HDR_VC_MODE_PROTECT;
if (stream->is_high_align)
val |= CSI_HIGH_ALIGN_RK3588;
else
val &= ~CSI_HIGH_ALIGN_RK3588;
rkcif_write_register(dev, get_reg_index_of_id_ctrl0(channel->id), val);
}
rkcif_write_register(dev, CIF_REG_MIPI_EFFECT_CODE_ID0, 0x02410251);
rkcif_write_register(dev, CIF_REG_MIPI_EFFECT_CODE_ID1, 0x02420252);
} else if (mbus_type == V4L2_MBUS_CCP2) {
@@ -4236,10 +4511,14 @@ static void rkcif_stream_stop(struct rkcif_stream *stream)
id = stream->id;
val = rkcif_read_register(cif_dev, get_reg_index_of_id_ctrl0(id));
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY)
val &= ~(CSI_ENABLE_CAPTURE | CSI_DMA_ENABLE);
else
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) {
if (cif_dev->chip_id >= CHIP_RK3576_CIF)
val &= ~(CSI_ENABLE_CAPTURE | CSI_DMA_ENABLE_RK3576);
else
val &= ~(CSI_ENABLE_CAPTURE | CSI_DMA_ENABLE);
} else {
val &= ~LVDS_ENABLE_CAPTURE;
}
if (cif_dev->channels[id].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) {
for (i = 0; i < cif_dev->channels[id].capture_info.multi_dev.dev_num; i++) {
@@ -4613,6 +4892,8 @@ void rkcif_buf_queue(struct vb2_buffer *vb)
}
if (rkcif_debug && addr && !hw_dev->iommu_en) {
memset(addr, 0, pixm->plane_fmt[i].sizeimage);
if (cifbuf->vb.vb2_buf.vb2_queue->mem_ops->finish)
cifbuf->vb.vb2_buf.vb2_queue->mem_ops->finish(cifbuf->vb.vb2_buf.planes[i].mem_priv);
v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev,
"Clear buffer, size: 0x%08x\n",
pixm->plane_fmt[i].sizeimage);
@@ -4931,7 +5212,7 @@ static int rkcif_create_dummy_buf(struct rkcif_stream *stream)
ret = rkcif_alloc_buffer(dev, dummy_buf);
if (ret) {
v4l2_err(&dev->v4l2_dev,
"Failed to allocate the memory for dummy buffer\n");
"Failed to allocate the memory for dummy buffer, size %d\n", max_size);
return -ENOMEM;
}
@@ -5150,13 +5431,17 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
}
}
}
stream->stopping = true;
ret = wait_event_timeout(stream->wq_stopped,
stream->state != RKCIF_STATE_STREAMING,
msecs_to_jiffies(500));
if (!ret) {
if (mode == RKCIF_STREAM_MODE_TOSCALE) {
rkcif_stream_stop(stream);
stream->stopping = false;
} else {
stream->stopping = true;
ret = wait_event_timeout(stream->wq_stopped,
stream->state != RKCIF_STATE_STREAMING,
msecs_to_jiffies(500));
if (!ret) {
rkcif_stream_stop(stream);
stream->stopping = false;
}
}
video_device_pipeline_stop(&node->vdev);
@@ -5270,14 +5555,16 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
if (can_reset && hw_dev->dummy_buf.vaddr)
rkcif_destroy_dummy_buf(stream);
}
if (mode == RKCIF_STREAM_MODE_CAPTURE)
if (mode == RKCIF_STREAM_MODE_CAPTURE) {
tasklet_disable(&stream->vb_done_tasklet);
INIT_LIST_HEAD(&stream->vb_done_list);
}
stream->cur_stream_mode &= ~mode;
INIT_LIST_HEAD(&stream->vb_done_list);
v4l2_info(&dev->v4l2_dev, "stream[%d] stopping finished, dma_en 0x%x\n", stream->id, stream->dma_en);
mutex_unlock(&dev->stream_lock);
rkcif_detach_sync_mode(dev);
if (mode == stream->cur_stream_mode)
rkcif_detach_sync_mode(dev);
}
static void rkcif_stop_streaming(struct vb2_queue *queue)
@@ -5417,10 +5704,6 @@ static u32 rkcif_determine_input_mode_rk3588(struct rkcif_stream *stream)
break;
}
}
if (stream->cif_fmt_in->field == V4L2_FIELD_NONE)
mode |= TRANSMIT_PROGRESS_RK3588;
else
mode |= TRANSMIT_INTERFACE_RK3588;
return mode;
}
@@ -5918,10 +6201,26 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
if (CIF_FETCH_IS_Y_FIRST(stream->cif_fmt_in->dvp_fmt_val))
yc_swap = BT1120_YC_SWAP;
}
} else {
} else if (dev->chip_id < CHIP_RK3562_CIF) {
if (sensor_info->mbus.type == V4L2_MBUS_BT656) {
if (stream->cif_fmt_in->field == V4L2_FIELD_NONE)
xfer_mode = BT1120_TRANSMIT_PROGRESS_RK3588;
else
xfer_mode = BT1120_TRANSMIT_INTERFACE_RK3588;
}
if ((inputmode & INPUT_BT1120_YUV422) == INPUT_BT1120_YUV422)
if (CIF_FETCH_IS_Y_FIRST(stream->cif_fmt_in->dvp_fmt_val))
yc_swap = BT1120_YC_SWAP_RK3588;
} else {
if (sensor_info->mbus.type == V4L2_MBUS_BT656) {
if (stream->cif_fmt_in->field == V4L2_FIELD_NONE)
xfer_mode = BT1120_TRANSMIT_PROGRESS_RK3576;
else
xfer_mode = BT1120_TRANSMIT_INTERFACE_RK3576;
}
if ((inputmode & INPUT_BT1120_YUV422) == INPUT_BT1120_YUV422)
if (CIF_FETCH_IS_Y_FIRST(stream->cif_fmt_in->dvp_fmt_val))
yc_swap = BT1120_YC_SWAP_RK3576;
}
if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
@@ -5961,6 +6260,7 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
| out_fmt_mask
| in_fmt_yuv_order
| multi_id_en
| xfer_mode
| sav_detect
| multi_id_sel | multi_id_mode | bt1120_edge_mode;
if (stream->is_high_align)
@@ -5968,6 +6268,8 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
else
val &= ~CIF_HIGH_ALIGN_RK3588;
}
if (dev->chip_id >= CHIP_RK3576_CIF)
val |= DVP_UVDS_EN;
rkcif_write_register(dev, CIF_REG_DVP_FOR, val);
if (dev->chip_id >= CHIP_RK3588_CIF) {
@@ -5995,6 +6297,9 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
dev->channels[stream->id].crop_en = 0;
}
if (dev->chip_id > CHIP_RK3562_CIF && stream->sw_dbg_en)
val = (val + 23) / 24 * 24;
rkcif_write_register(dev, CIF_REG_DVP_VIR_LINE_WIDTH, val);
rkcif_write_register(dev, CIF_REG_DVP_SET_SIZE,
dev->channels[stream->id].width |
@@ -6093,6 +6398,16 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
| DVP_SW_CAP_EN(stream->id)
| dma_en
| ENABLE_CAPTURE);
} else if (dev->chip_id == CHIP_RK3576_CIF) {
if (stream->dma_en)
dma_en = DVP_SW_DMA_EN_RK3676(stream->id);
if (stream->lack_buf_cnt == 2)
dma_en = 0;
rkcif_write_register(dev, CIF_REG_DVP_CTRL,
DVP_SW_WATER_LINE_25_RK3576
| DVP_SW_CAP_EN_RK3576(stream->id)
| dma_en
| ENABLE_CAPTURE);
} else {
rkcif_write_register(dev, CIF_REG_DVP_CTRL,
AXI_BURST_16 | workmode | ENABLE_CAPTURE);
@@ -6682,6 +6997,8 @@ int rkcif_set_fmt(struct rkcif_stream *stream,
bpl = width * bpp / CIF_YUV_STORED_BIT_WIDTH;
}
}
if (dev->chip_id > CHIP_RK3562_CIF && stream->sw_dbg_en)
bpl = (bpl + 23) / 24 * 24;
size = bpl * height;
imagesize += size;
ex_size = bpl * extend_line->pixm.height;
@@ -10165,6 +10482,18 @@ u32 rkcif_mbus_pixelcode_to_v4l2(u32 pixelcode)
case MEDIA_BUS_FMT_EBD_1X8:
pixelformat = V4l2_PIX_FMT_EBD8;
break;
case MEDIA_BUS_FMT_SBGGR16_1X16:
pixelformat = V4L2_PIX_FMT_SBGGR16;
break;
case MEDIA_BUS_FMT_SGBRG16_1X16:
pixelformat = V4L2_PIX_FMT_SGBRG16;
break;
case MEDIA_BUS_FMT_SGRBG16_1X16:
pixelformat = V4L2_PIX_FMT_SGRBG16;
break;
case MEDIA_BUS_FMT_SRGGB16_1X16:
pixelformat = V4L2_PIX_FMT_SRGGB16;
break;
default:
pixelformat = V4L2_PIX_FMT_SRGGB10;
}
@@ -10224,6 +10553,7 @@ void rkcif_enable_dma_capture(struct rkcif_stream *stream, bool is_only_enable)
struct v4l2_mbus_config *mbus_cfg = &cif_dev->active_sensor->mbus;
struct csi_channel_info *channel = &cif_dev->channels[stream->id];
u32 val = 0;
u32 uncompact = 0;
if (stream->buf_owner == RKCIF_DMAEN_BY_ISP)
stream->buf_owner = RKCIF_DMAEN_BY_ISP_TO_VICAP;
@@ -10257,11 +10587,18 @@ void rkcif_enable_dma_capture(struct rkcif_stream *stream, bool is_only_enable)
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) {
val = rkcif_read_register(cif_dev, get_reg_index_of_id_ctrl0(stream->id));
if (!stream->is_compact)
val |= CSI_WRDDR_TYPE_RAW_UNCOMPACT;
if (cif_dev->chip_id < CHIP_RK3576_CIF)
uncompact = CSI_WRDDR_TYPE_RAW_UNCOMPACT;
else
val &= ~CSI_WRDDR_TYPE_RAW_UNCOMPACT;
val |= CSI_DMA_ENABLE;
uncompact = CSI_WRDDR_TYPE_RAW_UNCOMPACT << 3;
if (!stream->is_compact)
val |= uncompact;
else
val &= ~uncompact;
if (cif_dev->chip_id < CHIP_RK3576_CIF)
val |= CSI_DMA_ENABLE;
else
val |= CSI_DMA_ENABLE_RK3576;
rkcif_write_register(cif_dev, get_reg_index_of_id_ctrl0(stream->id), val);
} else if (mbus_cfg->type == V4L2_MBUS_CCP2) {
val = rkcif_read_register(cif_dev, get_reg_index_of_lvds_id_ctrl0(stream->id));
@@ -10310,7 +10647,10 @@ static int rkcif_stop_dma_capture(struct rkcif_stream *stream)
if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY ||
mbus_cfg->type == V4L2_MBUS_CSI2_CPHY) {
val = rkcif_read_register(cif_dev, get_reg_index_of_id_ctrl0(stream->id));
val &= ~CSI_DMA_ENABLE;
if (cif_dev->chip_id < CHIP_RK3576_CIF)
val &= ~CSI_DMA_ENABLE;
else
val &= ~CSI_DMA_ENABLE_RK3576;
if (stream->is_stop_capture) {
val &= ~CSI_ENABLE_CAPTURE;
stream->is_stop_capture = false;
@@ -10385,6 +10725,30 @@ static int rkcif_g_toisp_fs(unsigned int intstat_glb, int index)
return -EINVAL;
}
static int rkcif_g_toisp_fs_rk3576(unsigned int intstat_glb, int index)
{
if (intstat_glb & TOISP_FS_CH0_RK3576(index))
return RKCIF_TOISP_CH0;
if (intstat_glb & TOISP_FS_CH1_RK3576(index))
return RKCIF_TOISP_CH1;
if (intstat_glb & TOISP_FS_CH2_RK3576(index))
return RKCIF_TOISP_CH2;
return -EINVAL;
}
static int rkcif_g_toisp_ch_rk3576(unsigned int intstat_glb, int index)
{
if (intstat_glb & TOISP_END_CH0_RK3576(index))
return RKCIF_TOISP_CH0;
if (intstat_glb & TOISP_END_CH1_RK3576(index))
return RKCIF_TOISP_CH1;
if (intstat_glb & TOISP_END_CH2_RK3576(index))
return RKCIF_TOISP_CH2;
return -EINVAL;
}
static void rkcif_toisp_check_stop_status(struct sditf_priv *priv,
unsigned int intstat_glb,
int index)
@@ -10398,7 +10762,10 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv,
int on = 0;
for (i = 0; i < TOISP_CH_MAX; i++) {
ch = rkcif_g_toisp_ch(intstat_glb, index);
if (priv->cif_dev->chip_id < CHIP_RK3576_CIF)
ch = rkcif_g_toisp_ch(intstat_glb, index);
else
ch = rkcif_g_toisp_ch_rk3576(intstat_glb, index);
if (ch >= 0) {
src_id = priv->toisp_inf.ch_info[ch].id;
if (src_id == 24)
@@ -10448,22 +10815,34 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv,
switch (ch) {
case RKCIF_TOISP_CH0:
val = TOISP_END_CH0(index);
if (priv->cif_dev->chip_id < CHIP_RK3576_CIF)
val = TOISP_END_CH0(index);
else
val = TOISP_END_CH0_RK3576(index);
intstat_glb = intstat_glb & (~val);
break;
case RKCIF_TOISP_CH1:
val = TOISP_END_CH1(index);
if (priv->cif_dev->chip_id < CHIP_RK3576_CIF)
val = TOISP_END_CH1(index);
else
val = TOISP_END_CH1_RK3576(index);
intstat_glb = intstat_glb & (~val);
break;
case RKCIF_TOISP_CH2:
val = TOISP_END_CH2(index);
if (priv->cif_dev->chip_id < CHIP_RK3576_CIF)
val = TOISP_END_CH2(index);
else
val = TOISP_END_CH2_RK3576(index);
intstat_glb = intstat_glb & (~val);
break;
default:
break;
}
}
ch = rkcif_g_toisp_fs(intstat_glb, index);
if (priv->cif_dev->chip_id < CHIP_RK3576_CIF)
ch = rkcif_g_toisp_fs(intstat_glb, index);
else
ch = rkcif_g_toisp_fs_rk3576(intstat_glb, index);
if (ch >= 0) {
src_id = priv->toisp_inf.ch_info[ch].id;
if (src_id == 24)
@@ -10495,15 +10874,24 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv,
}
switch (ch) {
case RKCIF_TOISP_CH0:
val = TOISP_FS_CH0(index);
if (priv->cif_dev->chip_id < CHIP_RK3576_CIF)
val = TOISP_FS_CH0(index);
else
val = TOISP_FS_CH0_RK3576(index);
intstat_glb = intstat_glb & (~val);
break;
case RKCIF_TOISP_CH1:
val = TOISP_FS_CH1(index);
if (priv->cif_dev->chip_id < CHIP_RK3576_CIF)
val = TOISP_FS_CH1(index);
else
val = TOISP_FS_CH1_RK3576(index);
intstat_glb = intstat_glb & (~val);
break;
case RKCIF_TOISP_CH2:
val = TOISP_FS_CH2(index);
if (priv->cif_dev->chip_id < CHIP_RK3576_CIF)
val = TOISP_FS_CH2(index);
else
val = TOISP_FS_CH2_RK3576(index);
intstat_glb = intstat_glb & (~val);
break;
default:
@@ -10674,13 +11062,13 @@ unsigned int rkcif_irq_global(struct rkcif_device *cif_dev)
if (intstat_glb & SCALE_TOISP_AXI0_ERR) {
v4l2_err(&cif_dev->v4l2_dev,
"ERROR: scale channel, AXI0 bus err intstat_glb:0x%x !!\n",
"ERROR: AXI0 bus err intstat_glb:0x%x !!\n",
intstat_glb);
return 0;
}
if (intstat_glb & SCALE_TOISP_AXI1_ERR) {
if (cif_dev->chip_id != CHIP_RK3576_CIF && intstat_glb & SCALE_TOISP_AXI1_ERR) {
v4l2_err(&cif_dev->v4l2_dev,
"ERROR: scale channel, AXI1 bus err intstat_glb:0x%x !!\n",
"ERROR: AXI1 bus err intstat_glb:0x%x !!\n",
intstat_glb);
return 0;
}
@@ -11634,7 +12022,8 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev)
}
for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
if (intstat & CSI_START_INTSTAT(i)) {
if (intstat & (cif_dev->chip_id < CHIP_RK3576_CIF ?
CSI_START_INTSTAT(i) : CSI_START_INTSTAT_RK3576(i))) {
stream = &cif_dev->stream[i];
if (i == 0) {
if (!stream->cur_skip_frame)

View File

@@ -56,6 +56,126 @@ static const struct cif_output_fmt scale_out_fmts[] = {
.bpp = { 16 },
.raw_bpp = 16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB8,
.cplanes = 1,
.mplanes = 1,
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG8,
.cplanes = 1,
.mplanes = 1,
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG8,
.cplanes = 1,
.mplanes = 1,
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR8,
.cplanes = 1,
.mplanes = 1,
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_GREY,
.cplanes = 1,
.mplanes = 1,
.bpp = {8},
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_Y12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_Y10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}
};
@@ -88,6 +208,18 @@ static u32 rkcif_scale_align_bits_per_pixel(struct rkcif_device *cif_dev,
if (fmt) {
switch (fmt->fourcc) {
case V4L2_PIX_FMT_SRGGB8:
case V4L2_PIX_FMT_SGRBG8:
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SBGGR8:
case V4L2_PIX_FMT_SRGGB10:
case V4L2_PIX_FMT_SGRBG10:
case V4L2_PIX_FMT_SGBRG10:
case V4L2_PIX_FMT_SBGGR10:
case V4L2_PIX_FMT_SRGGB12:
case V4L2_PIX_FMT_SGRBG12:
case V4L2_PIX_FMT_SGBRG12:
case V4L2_PIX_FMT_SBGGR12:
case V4L2_PIX_FMT_SBGGR16:
case V4L2_PIX_FMT_SGBRG16:
case V4L2_PIX_FMT_SGRBG16:
@@ -179,21 +311,31 @@ static int rkcif_scale_set_fmt(struct rkcif_scale_vdev *scale_vdev,
width = scale_vdev->src_res.width;
height = scale_vdev->src_res.height;
}
scale_ratio = width / pixm->width;
if (scale_ratio <= 8) {
scale_vdev->scale_mode = SCALE_8TIMES;
scale_times = 8;
} else if (scale_ratio <= 16) {
scale_vdev->scale_mode = SCALE_16TIMES;
scale_times = 16;
if (scale_vdev->scl_mode == RKCIF_SCL_MODE_SCALE) {
scale_ratio = width / pixm->width;
if (scale_ratio <= 8) {
scale_vdev->scale_mode = SCALE_8TIMES;
scale_times = 8;
} else if (scale_ratio <= 16) {
scale_vdev->scale_mode = SCALE_16TIMES;
scale_times = 16;
} else {
scale_vdev->scale_mode = SCALE_32TIMES;
scale_times = 32;
}
//source resolution align (scale_times * 2)
width = ALIGN(width, scale_times * 2);
pixm->width = width / (scale_times * 2) * 2;
pixm->height = height / (scale_times * 2) * 2;
} else {
scale_vdev->scale_mode = SCALE_32TIMES;
scale_times = 32;
pixm->width = width / 2;
pixm->height = height / 2;
if (pixm->width % 2 || pixm->height % 2) {
v4l2_err(&scale_vdev->cifdev->v4l2_dev,
"source width/height must multiple of 4\n");
return -1;
}
}
//source resolution align (scale_times * 2)
width = ALIGN(width, scale_times * 2);
pixm->width = width / (scale_times * 2) * 2;
pixm->height = height / (scale_times * 2) * 2;
pixm->num_planes = fmt->mplanes;
pixm->field = V4L2_FIELD_NONE;
pixm->quantization = V4L2_QUANTIZATION_DEFAULT;
@@ -543,10 +685,14 @@ static int rkcif_scale_stop(struct rkcif_scale_vdev *scale_vdev)
struct rkcif_device *dev = scale_vdev->cifdev;
int ch = scale_vdev->ch;
rkcif_write_register_and(dev, CIF_REG_SCL_CH_CTRL,
~(CIF_SCALE_EN(ch) |
CIF_SCALE_SW_SRC_CH(0x1f, ch) |
CIF_SCALE_SW_MODE(0x03, ch)));
if (dev->chip_id == CHIP_RK3576_CIF)
rkcif_write_register_and(dev, CIF_REG_SCL_CH_CTRL,
~(CIF_SCALE_EN(ch) | CIF_SCALE_DMA_EN_RK3576));
else
rkcif_write_register_and(dev, CIF_REG_SCL_CH_CTRL,
~(CIF_SCALE_EN(ch) |
CIF_SCALE_SW_SRC_CH(0x1f, ch) |
CIF_SCALE_SW_MODE(0x03, ch)));
scale_vdev->state = RKCIF_STATE_READY;
scale_vdev->frame_idx = 0;
return 0;
@@ -556,6 +702,7 @@ static void rkcif_scale_vb2_stop_streaming(struct vb2_queue *vq)
{
struct rkcif_scale_vdev *scale_vdev = vq->drv_priv;
struct rkcif_device *dev = scale_vdev->cifdev;
struct rkcif_stream *stream = scale_vdev->stream;
struct rkcif_buffer *buf = NULL;
int ret = 0;
@@ -584,6 +731,8 @@ static void rkcif_scale_vb2_stop_streaming(struct vb2_queue *vq)
list_del(&buf->queue);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
if (scale_vdev->scl_mode != RKCIF_SCL_MODE_SCALE)
rkcif_do_stop_stream(stream, RKCIF_STREAM_MODE_TOSCALE);
mutex_unlock(&dev->scale_lock);
}
@@ -820,13 +969,63 @@ static int rkcif_scale_channel_set(struct rkcif_scale_vdev *scale_vdev)
rkcif_write_register(dev, get_reg_index_of_scale_vlw(ch),
scale_vdev->ch_info.vir_width);
val = CIF_SCALE_SW_SRC_CH(scale_vdev->ch_src, ch) |
CIF_SCALE_SW_MODE(scale_vdev->scale_mode, ch) |
CIF_SCALE_EN(ch);
val |= CIF_SCALE_SW_MODE(scale_vdev->scale_mode, ch);
rkcif_write_register_or(dev, CIF_REG_SCL_CH_CTRL,
val);
return 0;
}
static int rkcif_scale_channel_set_rk3576(struct rkcif_scale_vdev *scale_vdev)
{
struct rkcif_device *dev = scale_vdev->cifdev;
u32 val = 0;
u32 ch = scale_vdev->ch;
val = rkcif_read_register(dev, CIF_REG_SCL_CH_CTRL);
if (val & CIF_SCALE_EN(ch)) {
v4l2_err(&dev->v4l2_dev, "scale_vdev[%d] has been used by other device\n", ch);
return -EINVAL;
}
rkcif_assign_scale_buffer_pingpong(scale_vdev,
RKCIF_YUV_ADDR_STATE_INIT,
ch);
rkcif_write_register_or(dev, CIF_REG_SCL_CTRL, SCALE_SOFT_RESET(scale_vdev->ch));
rkcif_write_register_and(dev, CIF_REG_GLB_INTST,
~(SCALE_END_INTSTAT_RK3576 |
SCALE_FIFO_OVERFLOW_RK3576));
rkcif_write_register_or(dev, CIF_REG_GLB_INTEN,
(SCALE_END_INTSTAT_RK3576 |
SCALE_FIFO_OVERFLOW_RK3576 |
SCALE_TOISP_AXI0_ERR));
val = CIF_SCALE_SW_WATER_LINE(1);
rkcif_write_register(dev, CIF_REG_SCL_CTRL, val);
val = scale_vdev->blc.pattern00 |
(scale_vdev->blc.pattern01 << 8) |
(scale_vdev->blc.pattern02 << 16) |
(scale_vdev->blc.pattern03 << 24);
rkcif_write_register(dev, CIF_REG_SCL_BLC_CH0 + ch,
val);
rkcif_write_register(dev, get_reg_index_of_scale_vlw(ch),
scale_vdev->ch_info.vir_width);
val = CIF_SCALE_SW_SRC_CH(scale_vdev->ch_src, ch) |
CIF_SCALE_EN(ch) | CIF_SCALE_DMA_EN_RK3576;
val |= (scale_vdev->scl_mode << 1);
if (scale_vdev->scl_mode == RKCIF_SCL_MODE_SCALE)
val |= CIF_SCALE_SW_MODE_RK3576(scale_vdev->scale_mode);
else if (scale_vdev->scl_mode == RKCIF_SCL_MODE_EXTRACTION)
val |= (scale_vdev->extrac_pattern << 10);
if (!scale_vdev->stream->is_compact)
val |= (1 << 12);
rkcif_write_register_or(dev, CIF_REG_SCL_CH_CTRL,
val);
return 0;
}
int rkcif_scale_start(struct rkcif_scale_vdev *scale_vdev)
{
@@ -842,7 +1041,10 @@ int rkcif_scale_start(struct rkcif_scale_vdev *scale_vdev)
}
rkcif_scale_channel_init(scale_vdev);
ret = rkcif_scale_channel_set(scale_vdev);
if (dev->chip_id < CHIP_RK3576_CIF)
ret = rkcif_scale_channel_set(scale_vdev);
else
ret = rkcif_scale_channel_set_rk3576(scale_vdev);
if (ret)
goto destroy_buf;
scale_vdev->frame_idx = 0;
@@ -877,13 +1079,11 @@ rkcif_scale_vb2_start_streaming(struct vb2_queue *queue,
struct rkcif_stream *stream = scale_vdev->stream;
int ret = 0;
if (stream->state == RKCIF_STATE_STREAMING) {
stream->to_en_scale = true;
} else {
ret = rkcif_scale_start(scale_vdev);
if (ret)
return ret;
}
ret = rkcif_scale_start(scale_vdev);
if (ret)
return ret;
if (scale_vdev->scl_mode != RKCIF_SCL_MODE_SCALE)
rkcif_do_start_stream(stream, RKCIF_STREAM_MODE_TOSCALE);
return 0;
}
@@ -922,34 +1122,40 @@ static int rkcif_scale_init_vb2_queue(struct vb2_queue *q,
}
static int rkcif_scale_g_ch(struct v4l2_device *v4l2_dev,
static int rkcif_scale_g_ch(struct rkcif_device *dev,
unsigned int intstat)
{
if (dev->chip_id == CHIP_RK3576_CIF) {
if (intstat & SCALE_END_INTSTAT_RK3576)
return 0;
else
return -EINVAL;
}
if (intstat & SCALE_END_INTSTAT(0)) {
if ((intstat & SCALE_END_INTSTAT(0)) ==
SCALE_END_INTSTAT(0))
v4l2_warn(v4l2_dev, "frame0/1 trigger simultaneously in CH0\n");
v4l2_warn(&dev->v4l2_dev, "frame0/1 trigger simultaneously in CH0\n");
return RKCIF_SCALE_CH0;
}
if (intstat & SCALE_END_INTSTAT(1)) {
if ((intstat & SCALE_END_INTSTAT(1)) ==
SCALE_END_INTSTAT(1))
v4l2_warn(v4l2_dev, "frame0/1 trigger simultaneously in CH1\n");
v4l2_warn(&dev->v4l2_dev, "frame0/1 trigger simultaneously in CH1\n");
return RKCIF_SCALE_CH1;
}
if (intstat & SCALE_END_INTSTAT(2)) {
if ((intstat & SCALE_END_INTSTAT(2)) ==
SCALE_END_INTSTAT(2))
v4l2_warn(v4l2_dev, "frame0/1 trigger simultaneously in CH2\n");
v4l2_warn(&dev->v4l2_dev, "frame0/1 trigger simultaneously in CH2\n");
return RKCIF_SCALE_CH2;
}
if (intstat & SCALE_END_INTSTAT(3)) {
if ((intstat & SCALE_END_INTSTAT(3)) ==
SCALE_END_INTSTAT(3))
v4l2_warn(v4l2_dev, "frame0/1 trigger simultaneously in CH3\n");
v4l2_warn(&dev->v4l2_dev, "frame0/1 trigger simultaneously in CH3\n");
return RKCIF_SCALE_CH3;
}
@@ -991,11 +1197,14 @@ static void rkcif_scale_update_stream(struct rkcif_scale_vdev *scale_vdev, int c
RKCIF_YUV_ADDR_STATE_UPDATE,
ch);
scale_vdev->frame_idx = scale_vdev->stream->frame_idx;
if (scale_vdev->scl_mode != RKCIF_SCL_MODE_SCALE)
scale_vdev->frame_idx++;
else
scale_vdev->frame_idx = scale_vdev->stream->frame_idx;
if (active_buf && (!ret)) {
vb_done = &active_buf->vb;
vb_done->vb2_buf.timestamp = ktime_get_ns();
vb_done->sequence = scale_vdev->frame_idx;
vb_done->sequence = scale_vdev->frame_idx - 1;
rkcif_scale_vb_done_oneframe(scale_vdev, vb_done);
}
}
@@ -1008,10 +1217,13 @@ void rkcif_irq_handle_scale(struct rkcif_device *cif_dev, unsigned int intstat_g
int i = 0;
u32 val = 0;
val = SCALE_FIFO_OVERFLOW(0) |
SCALE_FIFO_OVERFLOW(1) |
SCALE_FIFO_OVERFLOW(2) |
SCALE_FIFO_OVERFLOW(3);
if (cif_dev->chip_id < CHIP_RK3576_CIF)
val = SCALE_FIFO_OVERFLOW(0) |
SCALE_FIFO_OVERFLOW(1) |
SCALE_FIFO_OVERFLOW(2) |
SCALE_FIFO_OVERFLOW(3);
else
val = SCALE_FIFO_OVERFLOW_RK3576;
if (intstat_glb & val) {
v4l2_err(&cif_dev->v4l2_dev,
"ERROR: scale channel, overflow intstat_glb:0x%x !!\n",
@@ -1019,14 +1231,12 @@ void rkcif_irq_handle_scale(struct rkcif_device *cif_dev, unsigned int intstat_g
return;
}
ch = rkcif_scale_g_ch(&cif_dev->v4l2_dev,
intstat_glb);
ch = rkcif_scale_g_ch(cif_dev, intstat_glb);
if (ch < 0)
return;
for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
ch = rkcif_scale_g_ch(&cif_dev->v4l2_dev,
intstat_glb);
ch = rkcif_scale_g_ch(cif_dev, intstat_glb);
if (ch < 0)
continue;
@@ -1042,8 +1252,13 @@ void rkcif_irq_handle_scale(struct rkcif_device *cif_dev, unsigned int intstat_g
continue;
}
scale_vdev->frame_phase = SW_SCALE_END(intstat_glb, ch);
intstat_glb &= ~(SCALE_END_INTSTAT(ch));
if (cif_dev->chip_id < CHIP_RK3576_CIF) {
scale_vdev->frame_phase = SW_SCALE_END(intstat_glb, ch);
intstat_glb &= ~(SCALE_END_INTSTAT(ch));
} else {
scale_vdev->frame_phase = SW_SCALE_END_RK3576(intstat_glb);
intstat_glb &= ~(SCALE_END_INTSTAT_RK3576);
}
rkcif_scale_update_stream(scale_vdev, ch);
stream = scale_vdev->stream;
if (stream->to_en_dma)
@@ -1074,6 +1289,8 @@ void rkcif_init_scale_vdev(struct rkcif_device *cif_dev, u32 ch)
scale_vdev->blc.pattern01 = 0;
scale_vdev->blc.pattern02 = 0;
scale_vdev->blc.pattern03 = 0;
scale_vdev->scl_mode = RKCIF_SCL_MODE_SCALE;
scale_vdev->extrac_pattern = RKCIF_EXTRACTION_PATTERN_UP_LEFT;
INIT_LIST_HEAD(&scale_vdev->buf_head);
spin_lock_init(&scale_vdev->vbq_lock);
init_waitqueue_head(&scale_vdev->wq_stopped);

View File

@@ -67,7 +67,7 @@ static ssize_t rkcif_store_compact_mode(struct device *dev,
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int i, index;
char val[4];
char val[4] = {0};
if (buf) {
index = 0;
@@ -195,7 +195,7 @@ static ssize_t rkcif_store_memory_mode(struct device *dev,
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int i, index;
char val[4];
char val[4] = {0};
if (buf) {
index = 0;
@@ -256,7 +256,7 @@ static ssize_t rkcif_store_scale_ch0_blc(struct device *dev,
unsigned int temp = 0;
int ret = 0;
int j = 0;
char cha[2] = {0};
char cha[3] = {0};
if (buf) {
index = 0;
@@ -326,7 +326,7 @@ static ssize_t rkcif_store_scale_ch1_blc(struct device *dev,
unsigned int temp = 0;
int ret = 0;
int j = 0;
char cha[2] = {0};
char cha[3] = {0};
if (buf) {
index = 0;
@@ -398,7 +398,7 @@ static ssize_t rkcif_store_scale_ch2_blc(struct device *dev,
unsigned int temp = 0;
int ret = 0;
int j = 0;
char cha[2] = {0};
char cha[3] = {0};
if (buf) {
index = 0;
@@ -469,7 +469,7 @@ static ssize_t rkcif_store_scale_ch3_blc(struct device *dev,
unsigned int temp = 0;
int ret = 0;
int j = 0;
char cha[2] = {0};
char cha[3] = {0};
if (buf) {
index = 0;
@@ -527,7 +527,7 @@ static ssize_t rkcif_store_capture_fps(struct device *dev,
unsigned int temp = 0;
int ret = 0;
int j = 0;
char cha[2] = {0};
char cha[3] = {0};
struct rkcif_fps fps = {0};
if (buf) {
@@ -568,7 +568,7 @@ static ssize_t rkcif_store_capture_fps(struct device *dev,
return len;
}
static DEVICE_ATTR(fps, 0200, NULL, rkcif_store_capture_fps);
static DEVICE_ATTR(fps, 0600, NULL, rkcif_store_capture_fps);
static ssize_t rkcif_show_rdbk_debug(struct device *dev,
struct device_attribute *attr,
@@ -597,7 +597,233 @@ static ssize_t rkcif_store_rdbk_debug(struct device *dev,
dev_info(cif_dev->dev, "set rdbk debug failed\n");
return len;
}
static DEVICE_ATTR(rdbk_debug, 0200, rkcif_show_rdbk_debug, rkcif_store_rdbk_debug);
static DEVICE_ATTR(rdbk_debug, 0600, rkcif_show_rdbk_debug, rkcif_store_rdbk_debug);
static ssize_t rkcif_show_scl_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int ret;
ret = snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
cif_dev->scale_vdev[0].scl_mode,
cif_dev->scale_vdev[1].scl_mode,
cif_dev->scale_vdev[2].scl_mode,
cif_dev->scale_vdev[3].scl_mode);
return ret;
}
static ssize_t rkcif_store_scl_mode(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int i, index;
char val[4] = {0};
unsigned int temp = 0;
int ret = 0;
int j = 0;
char cha[3] = {0};
if (buf) {
index = 0;
for (i = 0; i < len; i++) {
if (((buf[i] == ' ') || (buf[i] == '\n')) && j) {
index++;
j = 0;
if (index == 4)
break;
continue;
} else {
if (buf[i] < '0' || buf[i] > '9')
continue;
cha[0] = buf[i];
cha[1] = '\0';
ret = kstrtoint(cha, 0, &temp);
if (!ret) {
if (j)
val[index] *= 10;
val[index] += temp;
j++;
}
}
}
for (i = 0; i < index; i++) {
if (val[i] < 4)
cif_dev->scale_vdev[i].scl_mode = val[i];
else
dev_info(cif_dev->dev, "set scl_mode failed, out of range\n");
}
}
return len;
}
static DEVICE_ATTR(scl_mode, 0600,
rkcif_show_scl_mode, rkcif_store_scl_mode);
static ssize_t rkcif_show_extraction_pattern(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int ret;
ret = snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
cif_dev->scale_vdev[0].extrac_pattern,
cif_dev->scale_vdev[1].extrac_pattern,
cif_dev->scale_vdev[2].extrac_pattern,
cif_dev->scale_vdev[3].extrac_pattern);
return ret;
}
static ssize_t rkcif_store_extraction_pattern(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int i, index;
char val[4] = {0};
unsigned int temp = 0;
int ret = 0;
int j = 0;
char cha[3] = {0};
if (buf) {
index = 0;
for (i = 0; i < len; i++) {
if (((buf[i] == ' ') || (buf[i] == '\n')) && j) {
index++;
j = 0;
if (index == 4)
break;
continue;
} else {
if (buf[i] < '0' || buf[i] > '9')
continue;
cha[0] = buf[i];
cha[1] = '\0';
ret = kstrtoint(cha, 0, &temp);
if (!ret) {
if (j)
val[index] *= 10;
val[index] += temp;
j++;
}
}
}
for (i = 0; i < index; i++) {
if (val[i] - '0' < 4)
cif_dev->scale_vdev[i].extrac_pattern = val[i];
else
dev_info(cif_dev->dev, "set extraction_pattern failed, out of range\n");
}
}
return len;
}
static DEVICE_ATTR(extraction_pattern, 0600,
rkcif_show_extraction_pattern, rkcif_store_extraction_pattern);
static ssize_t rkcif_show_sw_dbg_en(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int ret;
ret = snprintf(buf, PAGE_SIZE, "%d %d %d %d\n",
cif_dev->stream[0].sw_dbg_en ? 1 : 0,
cif_dev->stream[1].sw_dbg_en ? 1 : 0,
cif_dev->stream[2].sw_dbg_en ? 1 : 0,
cif_dev->stream[3].sw_dbg_en ? 1 : 0);
return ret;
}
static ssize_t rkcif_store_sw_dbg_en(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int i, index;
char val[4] = {0};
if (cif_dev->chip_id < CHIP_RK3576_CIF)
return len;
if (buf) {
index = 0;
for (i = 0; i < len; i++) {
if (buf[i] == ' ')
continue;
else if (buf[i] == '\0')
break;
val[index] = buf[i];
index++;
if (index == 4)
break;
}
for (i = 0; i < index; i++) {
if (val[i] - '0' == 0)
cif_dev->stream[i].sw_dbg_en = 0;
else
cif_dev->stream[i].sw_dbg_en = 1;
}
}
return len;
}
static DEVICE_ATTR(sw_dbg_en, 0600,
rkcif_show_sw_dbg_en, rkcif_store_sw_dbg_en);
static ssize_t rkcif_show_use_hw_interlace(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int ret;
ret = snprintf(buf, PAGE_SIZE, "%d\n",
cif_dev->use_hw_interlace);
return ret;
}
static ssize_t rkcif_store_use_hw_interlace(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
int val = 0;
int ret = 0;
ret = kstrtoint(buf, 0, &val);
if (!ret) {
if (val) {
if (cif_dev->inf_id == RKCIF_DVP ||
(cif_dev->inf_id == RKCIF_MIPI_LVDS && cif_dev->chip_id > CHIP_RK3562_CIF))
cif_dev->use_hw_interlace = true;
else
dev_info(cif_dev->dev, "not support to change merge mode of interlaced\n");
} else {
if (cif_dev->inf_id != RKCIF_DVP)
cif_dev->use_hw_interlace = false;
else
dev_info(cif_dev->dev, "not support to change merge mode of interlaced\n");
}
} else {
dev_info(cif_dev->dev, "set use_hw_interlace failed\n");
}
return len;
}
static DEVICE_ATTR(use_hw_interlace, 0600,
rkcif_show_use_hw_interlace, rkcif_store_use_hw_interlace);
static ssize_t rkcif_show_odd_frame_id(struct device *dev,
struct device_attribute *attr,
@@ -710,6 +936,10 @@ static struct attribute *dev_attrs[] = {
&dev_attr_rdbk_debug.attr,
&dev_attr_odd_frame_id.attr,
&dev_attr_odd_frame_first.attr,
&dev_attr_scl_mode.attr,
&dev_attr_extraction_pattern.attr,
&dev_attr_sw_dbg_en.attr,
&dev_attr_use_hw_interlace.attr,
NULL,
};
@@ -740,10 +970,15 @@ void rkcif_write_register(struct rkcif_device *dev,
csi_offset = dev->csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (dev->chip_id == CHIP_RK3576_CIF) {
if (dev->csi_host_idx < 2)
csi_offset = dev->csi_host_idx * 0x200;
else
csi_offset = 0x100 + dev->csi_host_idx * 0x100;
}
}
if (index < CIF_REG_INDEX_MAX) {
if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
if (index == CIF_REG_GLB_CTRL || index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
write_cif_reg(base, reg->offset + csi_offset, val);
v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev,
"write reg[0x%x]:0x%x!!!\n",
@@ -776,11 +1011,16 @@ void rkcif_write_register_or(struct rkcif_device *dev,
csi_offset = dev->csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (dev->chip_id == CHIP_RK3576_CIF) {
if (dev->csi_host_idx < 2)
csi_offset = dev->csi_host_idx * 0x200;
else
csi_offset = 0x100 + dev->csi_host_idx * 0x100;
}
}
if (index < CIF_REG_INDEX_MAX) {
if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
if (index == CIF_REG_GLB_CTRL || index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
reg_val = read_cif_reg(base, reg->offset + csi_offset);
reg_val |= val;
write_cif_reg(base, reg->offset + csi_offset, reg_val);
@@ -815,14 +1055,20 @@ void rkcif_write_register_and(struct rkcif_device *dev,
csi_offset = dev->csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (dev->chip_id == CHIP_RK3576_CIF) {
if (dev->csi_host_idx < 2)
csi_offset = dev->csi_host_idx * 0x200;
else
csi_offset = 0x100 + dev->csi_host_idx * 0x100;
}
}
if (index < CIF_REG_INDEX_MAX) {
if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
if (index == CIF_REG_GLB_CTRL || index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
reg_val = read_cif_reg(base, reg->offset + csi_offset);
reg_val &= val;
write_cif_reg(base, reg->offset + csi_offset, reg_val);
v4l2_dbg(4, rkcif_debug, &dev->v4l2_dev,
"write and reg[0x%x]:0x%x!!!\n",
reg->offset + csi_offset, val);
@@ -854,11 +1100,16 @@ unsigned int rkcif_read_register(struct rkcif_device *dev,
csi_offset = dev->csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (dev->chip_id == CHIP_RK3576_CIF) {
if (dev->csi_host_idx < 2)
csi_offset = dev->csi_host_idx * 0x200;
else
csi_offset = 0x100 + dev->csi_host_idx * 0x100;
}
}
if (index < CIF_REG_INDEX_MAX) {
if (index == CIF_REG_DVP_CTRL || reg->offset != 0x0)
if (index == CIF_REG_GLB_CTRL || index == CIF_REG_DVP_CTRL || reg->offset != 0x0)
val = read_cif_reg(base, reg->offset + csi_offset);
else
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
@@ -1790,9 +2041,7 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
return -EINVAL;
}
if (cif_dev->chip_id == CHIP_RK3588_CIF ||
cif_dev->chip_id == CHIP_RV1106_CIF ||
cif_dev->chip_id == CHIP_RK3562_CIF) {
if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
ret = rkcif_register_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH, true);
if (ret < 0) {
@@ -1823,9 +2072,7 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
return 0;
err_unreg_stream_vdev:
rkcif_unregister_stream_vdevs(cif_dev, stream_num);
if (cif_dev->chip_id == CHIP_RK3588_CIF ||
cif_dev->chip_id == CHIP_RV1106_CIF ||
cif_dev->chip_id == CHIP_RK3562_CIF)
if (cif_dev->chip_id >= CHIP_RK3588_CIF)
rkcif_unregister_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH);
if (cif_dev->chip_id > CHIP_RK1808_CIF)
@@ -2076,9 +2323,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID3);
}
if (cif_dev->chip_id == CHIP_RK3588_CIF ||
cif_dev->chip_id == CHIP_RV1106_CIF ||
cif_dev->chip_id == CHIP_RK3562_CIF) {
if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH0);
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH1);
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH2);

View File

@@ -74,8 +74,8 @@
#define RKCIF_MAX_CSI_CHANNEL 4
#define RKCIF_MAX_PIPELINE 4
#define RKCIF_DEFAULT_WIDTH 640
#define RKCIF_DEFAULT_HEIGHT 480
#define RKCIF_DEFAULT_WIDTH 64
#define RKCIF_DEFAULT_HEIGHT 48
#define RKCIF_FS_DETECTED_NUM 2
#define RKCIF_MAX_INTERVAL_NS 5000000
@@ -563,6 +563,7 @@ struct rkcif_stream {
int last_rx_buf_idx;
int last_frame_idx;
int new_fource_idx;
int sw_dbg_en;
atomic_t buf_cnt;
struct completion stop_complete;
struct rkcif_toisp_buf_state toisp_buf_state;
@@ -728,6 +729,8 @@ struct rkcif_scale_vdev {
unsigned int scale_mode;
int frame_phase;
unsigned int frame_idx;
int scl_mode;
int extrac_pattern;
bool stopping;
};

View File

@@ -971,6 +971,113 @@ static const struct cif_reg rk3562_cif_regs[] = {
[CIF_REG_TOISP0_CROP] = CIF_REG(TOISP0_CROP),
};
static const char * const rk3576_cif_clks[] = {
"aclk_cif",
"hclk_cif",
"dclk_cif",
"i0clk_cif",
"i1clk_cif",
"i2clk_cif",
"i3clk_cif",
"i4clk_cif",
};
static const char * const rk3576_cif_rsts[] = {
"rst_cif_a",
"rst_cif_h",
"rst_cif_d",
"rst_cif_iclk0",
"rst_cif_iclk1",
"rst_cif_iclk2",
"rst_cif_iclk3",
"rst_cif_iclk4",
};
static const struct cif_reg rk3576_cif_regs[] = {
[CIF_REG_DVP_CTRL] = CIF_REG(DVP_CTRL),
[CIF_REG_DVP_INTEN] = CIF_REG(DVP_INTEN),
[CIF_REG_DVP_INTSTAT] = CIF_REG(DVP_INTSTAT),
[CIF_REG_DVP_FOR] = CIF_REG(DVP_FOR),
[CIF_REG_DVP_SAV_EAV] = CIF_REG(DVP_SAV_EAV),
[CIF_REG_DVP_FRM0_ADDR_Y] = CIF_REG(DVP_FRM0_ADDR_Y_ID0),
[CIF_REG_DVP_FRM0_ADDR_UV] = CIF_REG(DVP_FRM0_ADDR_UV_ID0),
[CIF_REG_DVP_FRM1_ADDR_Y] = CIF_REG(DVP_FRM1_ADDR_Y_ID0),
[CIF_REG_DVP_FRM1_ADDR_UV] = CIF_REG(DVP_FRM1_ADDR_UV_ID0),
[CIF_REG_DVP_VIR_LINE_WIDTH] = CIF_REG(DVP_VIR_LINE_WIDTH),
[CIF_REG_DVP_SET_SIZE] = CIF_REG(DVP_CROP_SIZE),
[CIF_REG_DVP_CROP] = CIF_REG(DVP_CROP),
[CIF_REG_DVP_LINE_INT_NUM] = CIF_REG(DVP_LINE_INT_NUM_01),
[CIF_REG_DVP_LINE_CNT] = CIF_REG(DVP_LINE_CNT_01),
[CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG(CSI_MIPI0_ID0_CTRL0),
[CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG(CSI_MIPI0_ID0_CTRL1),
[CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG(CSI_MIPI0_ID1_CTRL0),
[CIF_REG_MIPI_LVDS_ID1_CTRL1] = CIF_REG(CSI_MIPI0_ID1_CTRL1),
[CIF_REG_MIPI_LVDS_ID2_CTRL0] = CIF_REG(CSI_MIPI0_ID2_CTRL0),
[CIF_REG_MIPI_LVDS_ID2_CTRL1] = CIF_REG(CSI_MIPI0_ID2_CTRL1),
[CIF_REG_MIPI_LVDS_ID3_CTRL0] = CIF_REG(CSI_MIPI0_ID3_CTRL0),
[CIF_REG_MIPI_LVDS_ID3_CTRL1] = CIF_REG(CSI_MIPI0_ID3_CTRL1),
[CIF_REG_MIPI_LVDS_CTRL] = CIF_REG(CSI_MIPI0_CTRL),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID0),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID0),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID0),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID0),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0] = CIF_REG(CSI_MIPI0_VLW_ID0),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID1),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID1),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID1),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID1),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1] = CIF_REG(CSI_MIPI0_VLW_ID1),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID2),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID2),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID2),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID2),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2] = CIF_REG(CSI_MIPI0_VLW_ID2),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID3),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID3),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID3),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID3),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3] = CIF_REG(CSI_MIPI0_VLW_ID3),
[CIF_REG_MIPI_LVDS_INTEN] = CIF_REG(CSI_MIPI0_INTEN),
[CIF_REG_MIPI_LVDS_INTSTAT] = CIF_REG(CSI_MIPI0_INTSTAT),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1] = CIF_REG(CSI_MIPI0_LINE_INT_NUM_ID0_1_RK3576),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3] = CIF_REG(CSI_MIPI0_LINE_INT_NUM_ID2_3_RK3576),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1] = CIF_REG(CSI_MIPI0_LINE_CNT_ID0_1_RK3576),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3] = CIF_REG(CSI_MIPI0_LINE_CNT_ID2_3_RK3576),
[CIF_REG_MIPI_LVDS_ID0_CROP_START] = CIF_REG(CSI_MIPI0_ID0_CROP_START_RK3576),
[CIF_REG_MIPI_LVDS_ID1_CROP_START] = CIF_REG(CSI_MIPI0_ID1_CROP_START_RK3576),
[CIF_REG_MIPI_LVDS_ID2_CROP_START] = CIF_REG(CSI_MIPI0_ID2_CROP_START_RK3576),
[CIF_REG_MIPI_LVDS_ID3_CROP_START] = CIF_REG(CSI_MIPI0_ID3_CROP_START_RK3576),
[CIF_REG_MIPI_FRAME_NUM_VC0] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC0_RK3576),
[CIF_REG_MIPI_FRAME_NUM_VC1] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC1_RK3576),
[CIF_REG_MIPI_FRAME_NUM_VC2] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC2_RK3576),
[CIF_REG_MIPI_FRAME_NUM_VC3] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC3_RK3576),
[CIF_REG_MIPI_EFFECT_CODE_ID0] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID0_RK3576),
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID1_RK3576),
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID2_RK3576),
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID3_RK3576),
[CIF_REG_MIPI_ON_PAD] = CIF_REG(CSI_MIPI0_ON_PAD_RK3576),
[CIF_REG_MIPI_SET_SIZE_ID0] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID0_RK3576),
[CIF_REG_MIPI_SET_SIZE_ID1] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID1_RK3576),
[CIF_REG_MIPI_SET_SIZE_ID2] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID2_RK3576),
[CIF_REG_MIPI_SET_SIZE_ID3] = CIF_REG(CSI_MIPI0_SET_FRAME_SIZE_ID3_RK3576),
[CIF_REG_GLB_CTRL] = CIF_REG(GLB_CTRL),
[CIF_REG_GLB_INTEN] = CIF_REG(GLB_INTEN),
[CIF_REG_GLB_INTST] = CIF_REG(GLB_INTST),
[CIF_REG_SCL_CH_CTRL] = CIF_REG(SCL_CH_CTRL),
[CIF_REG_SCL_CTRL] = CIF_REG(SCL_CTRL),
[CIF_REG_SCL_FRM0_ADDR_CH0] = CIF_REG(SCL_FRM0_ADDR_CH0),
[CIF_REG_SCL_FRM1_ADDR_CH0] = CIF_REG(SCL_FRM1_ADDR_CH0),
[CIF_REG_SCL_VLW_CH0] = CIF_REG(SCL_VLW_CH0),
[CIF_REG_SCL_BLC_CH0] = CIF_REG(SCL_BLC_CH0),
[CIF_REG_TOISP0_CTRL] = CIF_REG(TOISP0_CH_CTRL),
[CIF_REG_TOISP0_SIZE] = CIF_REG(TOISP0_CROP_SIZE),
[CIF_REG_TOISP0_CROP] = CIF_REG(TOISP0_CROP),
};
static const struct rkcif_hw_match_data px30_cif_match_data = {
.chip_id = CHIP_PX30_CIF,
.clks = px30_cif_clks,
@@ -1079,6 +1186,15 @@ static const struct rkcif_hw_match_data rk3562_cif_match_data = {
.cif_regs = rk3562_cif_regs,
};
static const struct rkcif_hw_match_data rk3576_cif_match_data = {
.chip_id = CHIP_RK3576_CIF,
.clks = rk3576_cif_clks,
.clks_num = ARRAY_SIZE(rk3576_cif_clks),
.rsts = rk3576_cif_rsts,
.rsts_num = ARRAY_SIZE(rk3576_cif_rsts),
.cif_regs = rk3576_cif_regs,
};
static const struct of_device_id rkcif_plat_of_match[] = {
#ifdef CONFIG_CPU_PX30
{
@@ -1149,6 +1265,12 @@ static const struct of_device_id rkcif_plat_of_match[] = {
.compatible = "rockchip,rk3562-cif",
.data = &rk3562_cif_match_data,
},
#endif
#ifdef CONFIG_CPU_RK3576
{
.compatible = "rockchip,rk3576-cif",
.data = &rk3576_cif_match_data,
},
#endif
{},
};

View File

@@ -107,6 +107,7 @@ enum rkcif_chip_id {
CHIP_RK3588_CIF,
CHIP_RV1106_CIF,
CHIP_RK3562_CIF,
CHIP_RK3576_CIF,
};
struct rkcif_hw_match_data {

View File

@@ -146,8 +146,10 @@ static int csi2_enable_clks(struct csi2_hw *csi2_hw)
{
int ret = 0;
if (!csi2_hw->clks_bulk)
return -EINVAL;
if (!csi2_hw->clks_bulk) {
dev_info(csi2_hw->dev, "clks is NULL, please check it if needs\n");
return 0;
}
ret = clk_bulk_prepare_enable(csi2_hw->clks_num, csi2_hw->clks_bulk);
if (ret)
@@ -190,6 +192,9 @@ static void csi2_enable(struct csi2_hw *csi2_hw,
write_csihost_reg(base, CSIHOST_N_LANES, lanes - 1);
if (csi2->sw_dbg)
val |= BIT(6);
if (host_type == RK_DSI_RXHOST) {
val |= SW_DSI_EN(1) | SW_DATATYPE_FS(0x01) |
SW_DATATYPE_FE(0x11) | SW_DATATYPE_LS(0x21) |
@@ -231,7 +236,8 @@ static int csi2_start(struct csi2_dev *csi2)
csi2_hw_do_reset(csi2->csi2_hw[csi_idx]);
ret = csi2_enable_clks(csi2->csi2_hw[csi_idx]);
if (ret) {
v4l2_err(&csi2->sd, "%s: enable clks failed\n", __func__);
v4l2_err(&csi2->sd, "%s: enable clks failed, index %d\n",
__func__, csi_idx);
return ret;
}
enable_irq(csi2->csi2_hw[csi_idx]->irq1);
@@ -587,7 +593,10 @@ static long rkcif_csi2_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg
if (csi2->match_data->chip_id > CHIP_RV1126_CSI2)
ret = v4l2_subdev_call(sensor, core, ioctl,
RKCIF_CMD_SET_CSI_IDX,
arg);
arg);
break;
case RKCIF_CMD_SET_PPI_DATA_DEBUG:
csi2->sw_dbg = *((u32 *)arg);
break;
default:
ret = -ENOIOCTLCMD;
@@ -603,6 +612,7 @@ static long rkcif_csi2_compat_ioctl32(struct v4l2_subdev *sd,
{
void __user *up = compat_ptr(arg);
struct rkcif_csi_info csi_info;
int sw_dbg = 0;
long ret;
switch (cmd) {
@@ -612,6 +622,12 @@ static long rkcif_csi2_compat_ioctl32(struct v4l2_subdev *sd,
ret = rkcif_csi2_ioctl(sd, cmd, &csi_info);
break;
case RKCIF_CMD_SET_PPI_DATA_DEBUG:
if (copy_from_user(&sw_dbg, up, sizeof(int)))
return -EFAULT;
ret = rkcif_csi2_ioctl(sd, cmd, &sw_dbg);
break;
default:
ret = -ENOIOCTLCMD;
break;
@@ -1022,6 +1038,12 @@ static const struct csi2_match_data rk3562_csi2_match_data = {
.num_hw = 4,
};
static const struct csi2_match_data rk3576_csi2_match_data = {
.chip_id = CHIP_RK3576_CSI2,
.num_pads = CSI2_NUM_PADS_MAX,
.num_hw = 5,
};
static const struct of_device_id csi2_dt_ids[] = {
{
.compatible = "rockchip,rk1808-mipi-csi2",
@@ -1051,6 +1073,10 @@ static const struct of_device_id csi2_dt_ids[] = {
.compatible = "rockchip,rk3562-mipi-csi2",
.data = &rk3562_csi2_match_data,
},
{
.compatible = "rockchip,rk3576-mipi-csi2",
.data = &rk3576_csi2_match_data,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, csi2_dt_ids);
@@ -1204,6 +1230,10 @@ static const struct csi2_hw_match_data rk3562_csi2_hw_match_data = {
.chip_id = CHIP_RK3562_CSI2,
};
static const struct csi2_hw_match_data rk3576_csi2_hw_match_data = {
.chip_id = CHIP_RK3576_CSI2,
};
static const struct of_device_id csi2_hw_ids[] = {
{
.compatible = "rockchip,rk1808-mipi-csi2-hw",
@@ -1231,7 +1261,11 @@ static const struct of_device_id csi2_hw_ids[] = {
},
{
.compatible = "rockchip,rk3562-mipi-csi2-hw",
.data = &rk3588_csi2_hw_match_data,
.data = &rk3562_csi2_hw_match_data,
},
{
.compatible = "rockchip,rk3576-mipi-csi2-hw",
.data = &rk3576_csi2_hw_match_data,
},
{ /* sentinel */ }
};

View File

@@ -27,8 +27,8 @@
#define CSI2_NUM_PADS_SINGLE_LINK 2
#define MAX_CSI2_SENSORS 2
#define RKCIF_DEFAULT_WIDTH 640
#define RKCIF_DEFAULT_HEIGHT 480
#define RKCIF_DEFAULT_WIDTH 64
#define RKCIF_DEFAULT_HEIGHT 48
#define CSI_ERRSTR_LEN (256)
#define CSI_VCINFO_LEN (12)
@@ -94,6 +94,7 @@ enum rkcsi2_chip_id {
CHIP_RK3588_CSI2,
CHIP_RV1106_CSI2,
CHIP_RK3562_CSI2,
CHIP_RK3576_CSI2,
};
enum csi2_pads {
@@ -171,6 +172,7 @@ struct csi2_dev {
int dsi_input_en;
struct rkcif_csi_info csi_info;
const char *dev_name;
int sw_dbg;
};
struct csi2_hw {

View File

@@ -149,6 +149,10 @@ enum cif_reg_index {
CIF_REG_MIPI_FRAME_SIZE_ID1,
CIF_REG_MIPI_FRAME_SIZE_ID2,
CIF_REG_MIPI_FRAME_SIZE_ID3,
CIF_REG_MIPI_SET_SIZE_ID0,
CIF_REG_MIPI_SET_SIZE_ID1,
CIF_REG_MIPI_SET_SIZE_ID2,
CIF_REG_MIPI_SET_SIZE_ID3,
CIF_REG_MIPI_ON_PAD,
CIF_REG_Y_STAT_CONTROL,
@@ -430,6 +434,28 @@ enum cif_reg_index {
#define CSI_MIPI0_FRAME_SIZE_ID2 0x1C8
#define CSI_MIPI0_FRAME_SIZE_ID3 0x1CC
#define CSI_MIPI0_LINE_INT_NUM_ID0_1_RK3576 0x1B0
#define CSI_MIPI0_LINE_INT_NUM_ID2_3_RK3576 0x1B4
#define CSI_MIPI0_LINE_CNT_ID0_1_RK3576 0x1B8
#define CSI_MIPI0_LINE_CNT_ID2_3_RK3576 0x1BC
#define CSI_MIPI0_ID0_CROP_START_RK3576 0x190
#define CSI_MIPI0_ID1_CROP_START_RK3576 0x194
#define CSI_MIPI0_ID2_CROP_START_RK3576 0x198
#define CSI_MIPI0_ID3_CROP_START_RK3576 0x19C
#define CSI_MIPI0_FRAME_NUM_VC0_RK3576 0x1D0
#define CSI_MIPI0_FRAME_NUM_VC1_RK3576 0x1D4
#define CSI_MIPI0_FRAME_NUM_VC2_RK3576 0x1D8
#define CSI_MIPI0_FRAME_NUM_VC3_RK3576 0x1DC
#define CSI_MIPI0_EFFECT_CODE_ID0_RK3576 0x180
#define CSI_MIPI0_EFFECT_CODE_ID1_RK3576 0x184
#define CSI_MIPI0_EFFECT_CODE_ID2_RK3576 0x188
#define CSI_MIPI0_EFFECT_CODE_ID3_RK3576 0x18C
#define CSI_MIPI0_ON_PAD_RK3576 0x17C
#define CSI_MIPI0_SET_FRAME_SIZE_ID0_RK3576 0x1A0
#define CSI_MIPI0_SET_FRAME_SIZE_ID1_RK3576 0x1A4
#define CSI_MIPI0_SET_FRAME_SIZE_ID2_RK3576 0x1A8
#define CSI_MIPI0_SET_FRAME_SIZE_ID3_RK3576 0x1AC
/* RV1106 CONTROL Registers Offset */
#define CIF_LVDS0_ID0_CTRL0 0x1D0
#define CIF_LVDS0_ID1_CTRL0 0x1D4
@@ -497,6 +523,10 @@ enum cif_reg_index {
#define DVP_SW_WATER_LINE_50 (0x1 << 5)
#define DVP_SW_WATER_LINE_25 (0x2 << 5)
#define DVP_SW_WATER_LINE_00 (0x3 << 5)
#define DVP_SW_WATER_LINE_75_RK3576 (0x0 << 20)
#define DVP_SW_WATER_LINE_50_RK3576 (0x1 << 20)
#define DVP_SW_WATER_LINE_25_RK3576 (0x2 << 20)
#define DVP_SW_WATER_LINE_00_RK3576 (0x3 << 20)
/* CIF_INTEN */
#define INTEN_DISABLE (0x0 << 0)
@@ -547,7 +577,9 @@ enum cif_reg_index {
#define DVP_SW_PRESS_VALUE(val) (((val) & 0x7) << 13)
#define DVP_SW_HURRY_VALUE(val) (((val) & 0x7) << 9)
#define DVP_SW_CAP_EN(ID) (2 << ID)
#define DVP_SW_CAP_EN_RK3576(ID) (0x10 << ID)
#define DVP_SW_DMA_EN(ID) (0x100000 << ID)
#define DVP_SW_DMA_EN_RK3676(ID) (0x100 << ID)
#define DVP_START_INTSTAT(ID) (0x3 << ((ID) * 2))
#define DVP_DMA_END_INTEN(id) \
@@ -633,6 +665,10 @@ enum cif_reg_index {
#define BT1120_CLOCK_DOUBLE_EDGES (0x01 << 24)
#define BT1120_TRANSMIT_INTERFACE (0x00 << 25)
#define BT1120_TRANSMIT_PROGRESS (0x01 << 25)
#define BT1120_TRANSMIT_INTERFACE_RK3588 (0x01 << 9)
#define BT1120_TRANSMIT_PROGRESS_RK3588 (0x00 << 9)
#define BT1120_TRANSMIT_INTERFACE_RK3576 (0x01 << 8)
#define BT1120_TRANSMIT_PROGRESS_RK3576 (0x00 << 8)
#define BT1120_YC_SWAP (0x01 << 26)
#define BT656_1120_MULTI_ID_DISABLE (0x00 << 28)
#define BT656_1120_MULTI_ID_ENABLE (0x01 << 28)
@@ -649,12 +685,12 @@ enum cif_reg_index {
#define CIF_HIGH_ALIGN_RK3588 (0x01 << 21)
#define BT656_DETECT_SAV (0X01 << 13)
#define BT656_DETECT_SAV_EAV (0X00 << 13)
#define DVP_UVDS_EN (1 << 14)
#define BT1120_CLOCK_SINGLE_EDGES_RK3588 (0x00 << 11)
#define BT1120_CLOCK_DOUBLE_EDGES_RK3588 (0x01 << 11)
#define TRANSMIT_INTERFACE_RK3588 (0x01 << 9)
#define TRANSMIT_PROGRESS_RK3588 (0x00 << 9)
#define BT1120_YC_SWAP_RK3588 (0x01 << 12)
#define BT1120_YC_SWAP_RK3576 (0x01 << 10)
#define INPUT_BT601_YUV422 (0x00 << 2)
#define INPUT_BT601_RAW (0x01 << 2)
#define INPUT_BT656_YUV422 (0x02 << 2)
@@ -748,7 +784,9 @@ enum cif_reg_index {
/* CIF SCALE*/
#define SCALE_END_INTSTAT(ch) (0x3 << ((ch + 1) * 2))
#define SCALE_END_INTSTAT_RK3576 (0x3 << 1)
#define SCALE_FIFO_OVERFLOW(ch) (1 << (10 + ch))
#define SCALE_FIFO_OVERFLOW_RK3576 (1 << 3)
#define SCALE_TOISP_AXI0_ERR (1 << 0)
#define SCALE_TOISP_AXI1_ERR (1 << 1)
#define CIF_SCALE_SW_PRESS_VALUE(val) (((val) & 0x7) << 13)
@@ -758,9 +796,12 @@ enum cif_reg_index {
#define CIF_SCALE_SW_WATER_LINE(val) (val << 1)
#define CIF_SCALE_SW_SRC_CH(val, ch) ((val & 0x1f) << (3 + ch * 8))
#define CIF_SCALE_SW_MODE(val, ch) ((val & 0x3) << (1 + ch * 8))
#define CIF_SCALE_SW_MODE_RK3576(val) ((val & 0x3) << 8)
#define CIF_SCALE_EN(ch) (1 << (ch * 8))
#define SW_SCALE_END(intstat, ch) ((intstat >> ((ch + 1) * 2)) & 0x3)
#define SW_SCALE_END_RK3576(intstat) (intstat >> 1)
#define SCALE_SOFT_RESET(ch) (0x1 << (ch + 16))
#define CIF_SCALE_DMA_EN_RK3576 (1 << 16)
/* CIF TOISP*/
#define CIF_TOISP0_FS(ch) (BIT(14) << ch)
@@ -768,15 +809,22 @@ enum cif_reg_index {
#define CIF_TOISP0_FE(ch) (BIT(20) << ch)
#define CIF_TOISP1_FE(ch) (BIT(23) << ch)
#define CIF_TOISP0_FS_RK3576(ch) (BIT(4) << ch)
#define CIF_TOISP0_FE_RK3576(ch) (BIT(7) << ch)
/* 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_RAW14_RK3588 (0x3 << 0)
#define CSI_WRDDR_TYPE_RGB888 (0x3 << 1)
#define CSI_WRDDR_TYPE_RGB888_RK3576 (0x7 << 4)
#define CSI_WRDDR_TYPE_RAW16 (0x4 << 4)
#define CSI_WRDDR_TYPE_YUV422 (0x4 << 1)
#define CSI_WRDDR_TYPE_YUV420SP (0x5 << 1)
#define CSI_WRDDR_TYPE_YUV420LEGACY (0xB << 4)
#define CSI_WRDDR_TYPE_YUV400 (0x6 << 1)
#define CSI_WRDDR_TYPE_RGB565 (0x7 << 1)
#define CSI_DISABLE_COMMAND_MODE (0x0 << 4)
@@ -785,6 +833,8 @@ enum cif_reg_index {
#define CSI_ENABLE_CROP (0x1 << 5)
#define CSI_DISABLE_CROP_V1 (0x0 << 4)
#define CSI_ENABLE_CROP_V1 (0x1 << 4)
#define CSI_DISABLE_CROP_RK3576 (0x0 << 1)
#define CSI_ENABLE_CROP_RK3576 (0x1 << 1)
#define CSI_ENABLE_MIPI_COMPACT (0x1 << 6)
#define CSI_YUV_INPUT_ORDER_UYVY (0x0 << 16)
#define CSI_YUV_INPUT_ORDER_VYUY (0x1 << 16)
@@ -792,6 +842,7 @@ enum cif_reg_index {
#define CSI_YUV_INPUT_ORDER_YVYU (0x3 << 16)
#define CSI_HIGH_ALIGN (0x1 << 31)
#define CSI_HIGH_ALIGN_RK3588 (0x1 << 27)
#define CSI_HIGH_ALIGN_RK3576 (0x1 << 11)
#define CSI_YUV_OUTPUT_ORDER_UYVY (0x0 << 18)
#define CSI_YUV_OUTPUT_ORDER_VYUY (0x1 << 18)
@@ -806,6 +857,8 @@ enum cif_reg_index {
#define CSI_ALIGN_MSB (0x01 << 27)
#define CSI_ALIGN_LSB (0x0 << 27)
#define CSI_DMA_ENABLE (0x1 << 28)
#define CSI_DMA_ENABLE_RK3576 (0x1 << 3)
#define CSI_UVDS_EN (1 << 16)
#define CSI_NO_HDR (0X0 << 22)
#define CSI_HDR2 (0X1 << 22)
@@ -893,11 +946,13 @@ enum cif_reg_index {
#define CSI_ALL_ERROR_INTEN_V1 (0xf0f << 16)
#define CSI_START_INTEN(id) (0x3 << ((id) * 2))
#define CSI_START_INTEN_RK3576(id) (0x1 << id)
#define CSI_DMA_END_INTEN(id) (0x3 << ((id) * 2 + 8))
#define CSI_LINE_INTEN(id) (0x1 << ((id) + 21))
#define CSI_LINE_INTEN_RK3588(id) (0x1 << ((id) + 20))
#define CSI_START_INTSTAT(id) (0x3 << ((id) * 2))
#define CSI_START_INTSTAT_RK3576(id) (0x1 << id)
#define CSI_DMA_END_INTSTAT(id) (0x3 << ((id) * 2 + 8))
#define CSI_LINE_INTSTAT(id) (0x1 << ((id) + 21))
#define CSI_LINE_INTSTAT_V1(id) (0x1 << ((id) + 20))
@@ -1026,6 +1081,10 @@ enum cif_reg_index {
#define RKCIF_SKIP_SHIFT 0X15
#define RKCIF_SKIP_EN(x) (0x1 << (8 + x))
#define RKCIF_CAP_SHIFT_RK3576 0x12
#define RKCIF_SKIP_SHIFT_RK3576 0x09
#define RKCIF_SKIP_EN_RK3576 (0x1 << 2)
/* CIF LVDS SAV EAV Define */
#define SW_LVDS_EAV_ACT(code) (((code) & 0xfff) << 16)
#define SW_LVDS_SAV_ACT(code) (((code) & 0xfff) << 0)
@@ -1072,4 +1131,12 @@ enum cif_reg_index {
#define TOISP_END_CH1(index) (0x1 << (21 + index * 3))
#define TOISP_END_CH2(index) (0x1 << (22 + index * 3))
#define TOISP_FS_CH0_RK3576(index) (0x1 << (4 + index * 3))
#define TOISP_FS_CH1_RK3576(index) (0x1 << (5 + index * 3))
#define TOISP_FS_CH2_RK3576(index) (0x1 << (6 + index * 3))
#define TOISP_END_CH0_RK3576(index) (0x1 << (7 + index * 3))
#define TOISP_END_CH1_RK3576(index) (0x1 << (8 + index * 3))
#define TOISP_END_CH2_RK3576(index) (0x1 << (9 + index * 3))
#endif

View File

@@ -493,10 +493,15 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user)
else
ch0 = 24;//dvp
ctrl_val = (ch0 << 3) | 0x1;
if (user == 0)
int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FE(0);
else
int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FE(0);
if (cif_dev->chip_id < CHIP_RK3576_CIF) {
if (user == 0)
int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FE(0);
else
int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FE(0);
} else {
if (user == 0)
int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FE_RK3576(0);
}
priv->toisp_inf.ch_info[0].is_valid = true;
priv->toisp_inf.ch_info[0].id = ch0;
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
@@ -504,12 +509,18 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user)
ch1 = cif_dev->csi_host_idx * 4;
ctrl_val = (ch0 << 3) | 0x1;
ctrl_val |= (ch1 << 11) | 0x100;
if (user == 0)
int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FS(1) |
CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1);
else
int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FS(1) |
CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1);
if (cif_dev->chip_id < CHIP_RK3576_CIF) {
if (user == 0)
int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FS(1) |
CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1);
else
int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FS(1) |
CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1);
} else {
if (user == 0)
int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FS_RK3576(1) |
CIF_TOISP0_FE_RK3576(0) | CIF_TOISP0_FE_RK3576(1);
}
priv->toisp_inf.ch_info[0].is_valid = true;
priv->toisp_inf.ch_info[0].id = ch0;
priv->toisp_inf.ch_info[1].is_valid = true;
@@ -521,12 +532,19 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user)
ctrl_val = (ch0 << 3) | 0x1;
ctrl_val |= (ch1 << 11) | 0x100;
ctrl_val |= (ch2 << 19) | 0x10000;
if (user == 0)
int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FS(1) | CIF_TOISP0_FS(2) |
CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1) | CIF_TOISP0_FE(2);
else
int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FS(1) | CIF_TOISP1_FS(2) |
CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1) | CIF_TOISP1_FE(2);
if (cif_dev->chip_id < CHIP_RK3576_CIF) {
if (user == 0)
int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FS(1) | CIF_TOISP0_FS(2) |
CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1) | CIF_TOISP0_FE(2);
else
int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FS(1) | CIF_TOISP1_FS(2) |
CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1) | CIF_TOISP1_FE(2);
} else {
if (user == 0)
int_en = CIF_TOISP0_FS_RK3576(0) | CIF_TOISP0_FS_RK3576(1) |
CIF_TOISP0_FS_RK3576(2) | CIF_TOISP0_FE_RK3576(0) |
CIF_TOISP0_FE_RK3576(1) | CIF_TOISP0_FE_RK3576(2);
}
priv->toisp_inf.ch_info[0].is_valid = true;
priv->toisp_inf.ch_info[0].id = ch0;
priv->toisp_inf.ch_info[1].is_valid = true;
@@ -534,6 +552,8 @@ static int sditf_channel_enable(struct sditf_priv *priv, int user)
priv->toisp_inf.ch_info[2].is_valid = true;
priv->toisp_inf.ch_info[2].id = ch2;
}
if (cif_dev->chip_id > CHIP_RK3562_CIF)
ctrl_val |= BIT(28);
if (user == 0) {
if (priv->toisp_inf.link_mode == TOISP_UNITE)
width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;

View File

@@ -39,6 +39,21 @@
#define RKCIF_CMD_SET_QUICK_STREAM \
_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct rkcif_quick_stream_param)
#define RKCIF_CMD_GET_SCL_MODE \
_IOR('V', BASE_VIDIOC_PRIVATE + 9, unsigned int)
#define RKCIF_CMD_SET_SCL_MODE \
_IOW('V', BASE_VIDIOC_PRIVATE + 10, unsigned int)
#define RKCIF_CMD_GET_EXTRACTION_PATTERN \
_IOR('V', BASE_VIDIOC_PRIVATE + 11, unsigned int)
#define RKCIF_CMD_SET_EXTRACTION_PATTERN \
_IOW('V', BASE_VIDIOC_PRIVATE + 12, unsigned int)
#define RKCIF_CMD_SET_PPI_DATA_DEBUG \
_IOW('V', BASE_VIDIOC_PRIVATE + 13, unsigned int)
/* cif memory mode
* 0: raw12/raw10/raw8 8bit memory compact
* 1: raw12/raw10 16bit memory one pixel
@@ -88,4 +103,16 @@ struct rkcif_quick_stream_param {
int resume_mode;
};
enum rkcif_scl_mode {
RKCIF_SCL_MODE_SCALE,
RKCIF_SCL_MODE_BINNING,
RKCIF_SCL_MODE_EXTRACTION,
};
enum rkcif_extraction_pattern {
RKCIF_EXTRACTION_PATTERN_UP_LEFT,
RKCIF_EXTRACTION_PATTERN_UP_RIGHT,
RKCIF_EXTRACTION_PATTERN_BOTTOM_LEFT,
RKCIF_EXTRACTION_PATTERN_BOTTOM_RIGHT,
};
#endif