media: rk-isp10: support bt656 signal interlace

odd and even field interlace generating a frame image.
fix cif_isp10_img_src_v4l2_subdev_enum_strm_fmts defrect info get error.
fix cif_isp10_rk3399 cif_clk_pll info doesn't match with dts config.

Change-Id: I44159c0dd4e676334221b5d5682e29d3280aa9fd
Signed-off-by: zhoupeng <benjo.zhou@rock-chips.com>
This commit is contained in:
zhoupeng
2017-09-08 19:07:33 +08:00
committed by Huang, Tao
parent 49418c68f6
commit 3565b1e7e8
7 changed files with 137 additions and 12 deletions

View File

@@ -460,6 +460,8 @@ static const char *cif_isp10_interface_string(
return "DVP_BT601_16Bit";
case PLTFRM_CAM_ITF_BT656_16:
return "DVP_BT656_16Bit";
case PLTFRM_CAM_ITF_BT656_8_INTERLACE:
return "DVP_BT656_8Bit_interlace";
default:
return "UNKNOWN/UNSUPPORTED";
}
@@ -1333,6 +1335,9 @@ static void cif_isp10_config_ism(struct cif_isp10_device *dev, bool async)
dev->config.base_addr + CIF_ISP_IS_H_SIZE);
cif_iowrite32(dev->config.isp_config.output.height,
dev->config.base_addr + CIF_ISP_IS_V_SIZE);
if (PLTFRM_CAM_ITF_INTERLACE(dev->config.cam_itf.type))
cif_iowrite32(dev->config.isp_config.output.height / 2,
dev->config.base_addr + CIF_ISP_IS_V_SIZE);
cif_iowrite32(0,
dev->config.base_addr + CIF_ISP_IS_CTRL);
}
@@ -1851,6 +1856,21 @@ static int cif_isp10_config_isp(
dev->config.base_addr + CIF_ISP_OUT_H_SIZE);
cif_iowrite32(output->height,
dev->config.base_addr + CIF_ISP_OUT_V_SIZE);
if (PLTFRM_CAM_ITF_INTERLACE(cam_itf->type)) {
cif_isp10_pltfrm_pr_info(dev->dev,
"type %s: input.size %dx%d, output.size %dx%d\n",
cif_isp10_interface_string(cam_itf->type),
dev->config.isp_config.input->defrect.width,
dev->config.isp_config.input->defrect.height,
output->width,
output->height);
cif_iowrite32(
dev->config.isp_config.input->defrect.height / 2,
dev->config.base_addr + CIF_ISP_ACQ_V_SIZE);
cif_iowrite32(
output->height / 2,
dev->config.base_addr + CIF_ISP_OUT_V_SIZE);
}
dev->isp_dev.input_width =
dev->config.isp_config.input->defrect.width;
@@ -2213,6 +2233,7 @@ static int cif_isp10_config_mi_sp(
u32 size = llength * height * bpp / 8;
u32 input_format = 0;
u32 output_format;
u32 burst_len;
u32 mi_ctrl;
dev->config.mi_config.sp.input =
@@ -2224,6 +2245,17 @@ static int cif_isp10_config_mi_sp(
width,
height,
llength);
if (PLTFRM_CAM_ITF_INTERLACE(dev->config.cam_itf.type)) {
llength = 2 * llength;
height = height / 2;
dev->config.mi_config.sp.vir_len_offset =
width;
burst_len = CIF_MI_CTRL_BURST_LEN_LUM_16 |
CIF_MI_CTRL_BURST_LEN_CHROM_16;
} else {
burst_len = CIF_MI_CTRL_BURST_LEN_LUM_64 |
CIF_MI_CTRL_BURST_LEN_CHROM_64;
}
if (!CIF_ISP10_PIX_FMT_IS_YUV(in_pix_fmt)) {
cif_isp10_pltfrm_pr_err(dev->dev,
@@ -2268,12 +2300,16 @@ static int cif_isp10_config_mi_sp(
(CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 0))
output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV400;
else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
(CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 2))
(CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 2)) {
output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV420;
else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
(CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
dev->config.mi_config.sp.vir_len_offset =
width;
} else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
(CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4)) {
output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV422;
else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 4) &&
dev->config.mi_config.sp.vir_len_offset =
width * 2;
} else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 4) &&
(CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV444;
else {
@@ -2378,8 +2414,7 @@ static int cif_isp10_config_mi_sp(
CIF_MI_CTRL_SP_WRITE_FMT(writeformat) |
input_format |
output_format |
CIF_MI_CTRL_BURST_LEN_LUM_64 |
CIF_MI_CTRL_BURST_LEN_CHROM_64 |
burst_len |
CIF_MI_CTRL_INIT_BASE_EN |
CIF_MI_CTRL_INIT_OFFSET_EN |
CIF_MI_SP_AUTOUPDATE_ENABLE;
@@ -3766,6 +3801,8 @@ err:
static int cif_isp10_update_mi_sp(
struct cif_isp10_device *dev)
{
u32 vir_len_offset = dev->config.mi_config.sp.vir_len_offset;
cif_isp10_pltfrm_pr_dbg(NULL,
"curr 0x%08x next 0x%08x\n",
dev->config.mi_config.sp.curr_buff_addr,
@@ -3792,6 +3829,56 @@ static int cif_isp10_update_mi_sp(
cif_isp10_mi_update_buff_addr(dev, CIF_ISP10_STREAM_SP);
dev->config.mi_config.sp.curr_buff_addr =
dev->config.mi_config.sp.next_buff_addr;
} else if (PLTFRM_CAM_ITF_INTERLACE(dev->config.cam_itf.type)) {
cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr +
vir_len_offset,
dev->config.base_addr +
CIF_MI_SP_Y_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr +
vir_len_offset +
dev->config.mi_config.sp.cb_offs,
dev->config.base_addr +
CIF_MI_SP_CB_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr +
vir_len_offset +
dev->config.mi_config.sp.cr_offs,
dev->config.base_addr +
CIF_MI_SP_CR_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
/*
* There have bee repeatedly issues with
* the offset registers, it is safer to write
* them each time, even though it is always
* 0 and even though that is the
* register's default value
*/
cif_iowrite32_verify(0,
dev->config.base_addr +
CIF_MI_SP_Y_OFFS_CNT_INIT,
CIF_MI_ADDR_SIZE_ALIGN_MASK);
cif_iowrite32_verify(0,
dev->config.base_addr +
CIF_MI_SP_CB_OFFS_CNT_INIT,
CIF_MI_ADDR_SIZE_ALIGN_MASK);
cif_iowrite32_verify(0,
dev->config.base_addr +
CIF_MI_SP_CR_OFFS_CNT_INIT,
CIF_MI_ADDR_SIZE_ALIGN_MASK);
cif_isp10_pltfrm_pr_dbg(dev->dev,
"\n MI_SP_Y_BASE_AD 0x%08x/0x%08x\n"
" MI_SP_CB_BASE_AD 0x%08x/0x%08x\n"
" MI_SP_CR_BASE_AD 0x%08x/0x%08x\n",
cif_ioread32(dev->config.base_addr +
CIF_MI_SP_Y_BASE_AD_INIT),
cif_ioread32(dev->config.base_addr +
CIF_MI_SP_Y_BASE_AD_SHD),
cif_ioread32(dev->config.base_addr +
CIF_MI_SP_CB_BASE_AD_INIT),
cif_ioread32(dev->config.base_addr +
CIF_MI_SP_CB_BASE_AD_SHD),
cif_ioread32(dev->config.base_addr +
CIF_MI_SP_CR_BASE_AD_INIT),
cif_ioread32(dev->config.base_addr +
CIF_MI_SP_CR_BASE_AD_SHD));
}
return 0;
@@ -4068,6 +4155,12 @@ static int cif_isp10_mi_frame_end(
cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
cif_isp10_stream_id_string(stream_id));
/* BIT 2(current field information): 0 = odd, 1 = even */
if (PLTFRM_CAM_ITF_INTERLACE(dev->config.cam_itf.type))
dev->config.mi_config.sp.field_flag =
(cif_ioread32(dev->config.base_addr +
CIF_ISP_FLAGS_SHD) & 0x4) >> 2;
if (stream_id == CIF_ISP10_STREAM_MP) {
stream = &dev->mp_stream;
y_base_addr =
@@ -4136,7 +4229,8 @@ static int cif_isp10_mi_frame_end(
&stream->next_buf->vb.vb2_buf, 0);
tmp_addr = sg_dma_address(sgt->sgl);
#endif
if (tmp_addr != cif_ioread32(y_base_addr)) {
if (tmp_addr != cif_ioread32(y_base_addr) &&
!PLTFRM_CAM_ITF_INTERLACE(dev->config.cam_itf.type)) {
cif_isp10_pltfrm_pr_warn(dev->dev,
"%s buffer queue is not advancing (0x%08x/0x%08x)\n",
cif_isp10_stream_id_string(stream_id),
@@ -4148,6 +4242,13 @@ static int cif_isp10_mi_frame_end(
cif_ioread32(y_base_addr));
stream->stall = true;
}
if (PLTFRM_CAM_ITF_INTERLACE(dev->config.cam_itf.type)) {
if (dev->config.mi_config.sp.field_flag)
stream->stall = true;
else
stream->stall = false;
}
}
if (!stream->stall) {

View File

@@ -432,6 +432,11 @@ struct cif_isp10_mi_path_config {
u32 cb_size;
u32 cr_size;
bool busy;
/* FOR BT655: 0 = ODD, 1 = EVEN */
bool field_flag;
/* for interlace offset */
u32 vir_len_offset;
};
struct cif_isp10_zoom_buffer_info {

View File

@@ -70,6 +70,12 @@ static enum cif_isp10_pix_fmt img_src_v4l2_subdev_pix_fmt2cif_isp10_pix_fmt(
case MEDIA_BUS_FMT_YUYV8_1X16:
case MEDIA_BUS_FMT_YUYV10_1X20:
return CIF_YUV422I;
case MEDIA_BUS_FMT_YVYU8_1_5X8:
case MEDIA_BUS_FMT_YVYU8_2X8:
case MEDIA_BUS_FMT_YVYU10_2X10:
case MEDIA_BUS_FMT_YVYU8_1X16:
case MEDIA_BUS_FMT_YVYU10_1X20:
return CIF_YVU422I;
case MEDIA_BUS_FMT_UYVY8_1_5X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_UYVY8_1X16:
@@ -132,6 +138,8 @@ static int cif_isp10_pix_fmt2img_src_v4l2_subdev_pix_fmt(
switch (cif_isp10_pix_fmt) {
case CIF_YUV422I:
return MEDIA_BUS_FMT_YUYV8_2X8;
case CIF_YVU422I:
return MEDIA_BUS_FMT_YVYU8_2X8;
case CIF_UYV422I:
return MEDIA_BUS_FMT_UYVY8_2X8;
case CIF_RGB565:
@@ -275,7 +283,7 @@ int cif_isp10_img_src_v4l2_subdev_enum_strm_fmts(
defrect.width = fie.width;
defrect.height = fie.height;
memset(&defrect, 0x00, sizeof(struct v4l2_rect));
memset(&defrect.defrect, 0x00, sizeof(defrect.defrect));
v4l2_subdev_call(subdev,
core,
ioctl,

View File

@@ -567,7 +567,7 @@ static int soc_init(struct pltfrm_soc_init_para *init)
clk_rst->cif_clk_out =
devm_clk_get(&pdev->dev, "clk_cif_out");
clk_rst->cif_clk_pll =
devm_clk_get(&pdev->dev, "cif_clk_pll");
devm_clk_get(&pdev->dev, "clk_cif_pll");
clk_rst->pclk_dphy_ref =
devm_clk_get(&pdev->dev, "pclk_dphy_ref");
@@ -610,7 +610,7 @@ static int soc_init(struct pltfrm_soc_init_para *init)
clk_rst->cif_clk_out =
devm_clk_get(&pdev->dev, "clk_cif_out");
clk_rst->cif_clk_pll =
devm_clk_get(&pdev->dev, "cif_clk_pll");
devm_clk_get(&pdev->dev, "clk_cif_pll");
clk_rst->pclk_dphy_ref =
devm_clk_get(&pdev->dev, "pclk_dphy_ref");

View File

@@ -343,6 +343,8 @@ static enum cif_isp10_pix_fmt cif_isp10_v4l2_pix_fmt2cif_isp10_pix_fmt(
return CIF_YVU420SP;
case V4L2_PIX_FMT_YUYV:
return CIF_YUV422I;
case V4L2_PIX_FMT_YVYU:
return CIF_YVU422I;
case V4L2_PIX_FMT_UYVY:
return CIF_UYV422I;
case V4L2_PIX_FMT_YUV422P:

View File

@@ -65,8 +65,13 @@
*v0.1.8:
*Fix oops error when soc_clk_disable is called in rk3399.
*
*v0.1.9:
*1. Support bt656 signal interlace: odd and even field interlace generating
*a frame image.
*2. fix cif_isp10_img_src_v4l2_subdev_enum_strm_fmts defrect info get error.
*3. fix cif_isp10_rk3399 cif_clk_pll info doesn't match with dts config.
*/
#define CONFIG_CIFISP10_DRIVER_VERSION KERNEL_VERSION(0, 1, 8)
#define CONFIG_CIFISP10_DRIVER_VERSION KERNEL_VERSION(0, 1, 9)
#endif

View File

@@ -47,12 +47,14 @@ enum pltfrm_cam_itf_type {
PLTFRM_CAM_ITF_BT601_12 = 0x200000B1,
PLTFRM_CAM_ITF_BT656_12 = 0x200000B2,
PLTFRM_CAM_ITF_BT601_16 = 0x200000F1,
PLTFRM_CAM_ITF_BT656_16 = 0x200000F2
PLTFRM_CAM_ITF_BT656_16 = 0x200000F2,
PLTFRM_CAM_ITF_BT656_8_INTERLACE = 0x20000172
};
#define PLTFRM_CAM_ITF_MAIN_MASK 0xf0000000
#define PLTFRM_CAM_ITF_SUB_MASK 0x0000000f
#define PLTFRM_CAM_ITF_DVP_BW_MASK 0x000000f0
#define PLTFRM_CAM_ITF_INTERLACE_MASK 0x00000100
#define PLTFRM_CAM_ITF_IS_MIPI(a) \
(((a) & PLTFRM_CAM_ITF_MAIN_MASK) == 0x10000000)
@@ -64,6 +66,8 @@ enum pltfrm_cam_itf_type {
(((a) & PLTFRM_CAM_ITF_SUB_MASK) == 0x01))
#define PLTFRM_CAM_ITF_DVP_BW(a) \
((((a) & PLTFRM_CAM_ITF_DVP_BW_MASK) >> 4) + 1)
#define PLTFRM_CAM_ITF_INTERLACE(a) \
(((a) & PLTFRM_CAM_ITF_INTERLACE_MASK) == 0x00000100)
struct pltfrm_cam_mipi_config {
u32 dphy_index;