From 3565b1e7e83fef2baede127fb471be9edad99745 Mon Sep 17 00:00:00 2001 From: zhoupeng Date: Fri, 8 Sep 2017 19:07:33 +0800 Subject: [PATCH] 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 --- drivers/media/platform/rk-isp10/cif_isp10.c | 115 ++++++++++++++++-- drivers/media/platform/rk-isp10/cif_isp10.h | 5 + .../rk-isp10/cif_isp10_img_src_v4l2-subdev.c | 10 +- .../platform/rk-isp10/cif_isp10_rk3399.c | 4 +- .../media/platform/rk-isp10/cif_isp10_v4l2.c | 2 + .../platform/rk-isp10/cif_isp10_version.h | 7 +- .../linux/platform_data/rk_isp10_platform.h | 6 +- 7 files changed, 137 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/rk-isp10/cif_isp10.c b/drivers/media/platform/rk-isp10/cif_isp10.c index dd44afe2bedf..1eb81eb96c16 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10.c +++ b/drivers/media/platform/rk-isp10/cif_isp10.c @@ -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) { diff --git a/drivers/media/platform/rk-isp10/cif_isp10.h b/drivers/media/platform/rk-isp10/cif_isp10.h index cdc0a74c63d5..421a68ea34cb 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10.h +++ b/drivers/media/platform/rk-isp10/cif_isp10.h @@ -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 { diff --git a/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c b/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c index 9871d9e8fbf9..dce595f2d3e3 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_img_src_v4l2-subdev.c @@ -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, diff --git a/drivers/media/platform/rk-isp10/cif_isp10_rk3399.c b/drivers/media/platform/rk-isp10/cif_isp10_rk3399.c index f67b9890e391..5a83729caa42 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_rk3399.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_rk3399.c @@ -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"); diff --git a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c index 2fa5c2d056cf..bd6899e8ea72 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c +++ b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c @@ -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: diff --git a/drivers/media/platform/rk-isp10/cif_isp10_version.h b/drivers/media/platform/rk-isp10/cif_isp10_version.h index 8ba92000af15..c88a3e25cd06 100644 --- a/drivers/media/platform/rk-isp10/cif_isp10_version.h +++ b/drivers/media/platform/rk-isp10/cif_isp10_version.h @@ -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 diff --git a/include/linux/platform_data/rk_isp10_platform.h b/include/linux/platform_data/rk_isp10_platform.h index 8974945f9441..1aa8a629c326 100644 --- a/include/linux/platform_data/rk_isp10_platform.h +++ b/include/linux/platform_data/rk_isp10_platform.h @@ -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;