diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 6a33a2aaa8f2..1736fdeb30e7 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -262,6 +262,12 @@ static const struct cif_output_fmt out_fmts[] = { .mplanes = 1, .bpp = { 16 }, .fmt_type = CIF_FMT_TYPE_RAW, + }, { + .fourcc = V4L2_PIX_FMT_GREY, + .cplanes = 1, + .mplanes = 1, + .bpp = {8}, + .fmt_type = CIF_FMT_TYPE_RAW, } /* TODO: We can support NV12M/NV21M/NV16M/NV61M too */ @@ -2007,6 +2013,7 @@ static u32 rkcif_align_bits_per_pixel(const struct cif_output_fmt *fmt, case V4L2_PIX_FMT_YVYU: case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_GREY: case V4L2_PIX_FMT_Y16: bpp = fmt->bpp[plane_index]; break; @@ -2016,6 +2023,7 @@ static u32 rkcif_align_bits_per_pixel(const struct cif_output_fmt *fmt, 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: @@ -2335,6 +2343,7 @@ static int rkcif_stream_start(struct rkcif_stream *stream) atomic_set(&sof_sd->frm_sync_seq, 0); stream->state = RKCIF_STATE_STREAMING; + stream->cifdev->dvp_sof_in_oneframe = 0; return 0; } @@ -4698,14 +4707,21 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) lastpix = CIF_FETCH_Y_LAST_LINE(lastpix); ctl = rkcif_read_register(cif_dev, CIF_REG_DVP_CTRL); + rkcif_write_register(cif_dev, CIF_REG_DVP_INTSTAT, intstat); + stream = &cif_dev->stream[RKCIF_STREAM_CIF]; - if ((intstat & LINE_INT_END) && !(intstat & (FRAME_END))) { - rkcif_dvp_event_inc_sof(cif_dev); - rkcif_write_register(cif_dev, CIF_REG_DVP_INTSTAT, intstat); - int_en = rkcif_read_register(cif_dev, CIF_REG_DVP_INTEN); - int_en &= ~LINE_INT_EN; - rkcif_write_register(cif_dev, CIF_REG_DVP_INTEN, int_en); + if ((intstat & LINE_INT_END) && !(intstat & FRAME_END) && + (cif_dev->dvp_sof_in_oneframe == 0)) { + if ((intstat & (PRE_INF_FRAME_END | PST_INF_FRAME_END)) == 0x0) { + if ((intstat & INTSTAT_ERR) == 0x0) { + rkcif_dvp_event_inc_sof(cif_dev); + int_en = rkcif_read_register(cif_dev, CIF_REG_DVP_INTEN); + int_en &= ~LINE_INT_EN; + rkcif_write_register(cif_dev, CIF_REG_DVP_INTEN, int_en); + cif_dev->dvp_sof_in_oneframe = 1; + } + } } if (intstat & BUS_ERR) { @@ -4741,8 +4757,6 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) * a frame ready */ if ((intstat & PST_INF_FRAME_END)) { - rkcif_write_register(cif_dev, CIF_REG_DVP_INTSTAT, - PST_INF_FRAME_END_CLR); if (stream->stopping) /* To stop CIF ASAP, before FRAME_END irq */ @@ -4753,12 +4767,10 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) if ((intstat & FRAME_END)) { struct vb2_v4l2_buffer *vb_done = NULL; - rkcif_write_register(cif_dev, CIF_REG_DVP_INTSTAT, - FRAME_END_CLR); - int_en = rkcif_read_register(cif_dev, CIF_REG_DVP_INTEN); int_en |= LINE_INT_EN; rkcif_write_register(cif_dev, CIF_REG_DVP_INTEN, int_en); + cif_dev->dvp_sof_in_oneframe = 0; if (stream->stopping) { rkcif_stream_stop(stream); @@ -4778,6 +4790,8 @@ void rkcif_irq_pingpong(struct rkcif_device *cif_dev) if (lastline != stream->pixm.height || (!(cif_frmst & CIF_F0_READY) && !(cif_frmst & CIF_F1_READY))) { + + cif_dev->dvp_sof_in_oneframe = 1; v4l2_err(&cif_dev->v4l2_dev, "Bad frame, pp irq:0x%x frmst:0x%x size:%dx%d\n", intstat, cif_frmst, lastpix, lastline); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 0bc3995ffb3e..4c2d36be8a57 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -506,6 +506,7 @@ struct rkcif_device { unsigned int buf_wake_up_cnt; bool iommu_en; + unsigned int dvp_sof_in_oneframe; }; extern struct platform_driver rkcif_plat_drv; diff --git a/drivers/media/platform/rockchip/cif/regs.h b/drivers/media/platform/rockchip/cif/regs.h index 8cf56b10e2c8..71b3ec9d11ee 100644 --- a/drivers/media/platform/rockchip/cif/regs.h +++ b/drivers/media/platform/rockchip/cif/regs.h @@ -311,20 +311,21 @@ enum cif_reg_index { #define FRAME_END_EN (0x1 << 0) #define BUS_ERR_EN (0x1 << 6) #define SCL_ERR_EN (0x1 << 7) +#define PRE_INF_FRAME_END_EN (0x1 << 8) #define PST_INF_FRAME_END_EN (0x1 << 9) #define LINE_INT_EN (0x1 << 10) /* CIF INTSTAT */ #define INTSTAT_CLS (0x3FF) #define FRAME_END (0x01 << 0) -#define LINE_ERR (0x1 << 2) -#define PIX_ERR (0x1 << 3) -#define IFIFO_OVERFLOW (0x1 << 4) -#define DFIFO_OVERFLOW (0x1 << 5) -#define BUS_ERR (0x1 << 6) +#define LINE_ERR (0x01 << 2) +#define PIX_ERR (0x01 << 3) +#define IFIFO_OVERFLOW (0x01 << 4) +#define DFIFO_OVERFLOW (0x01 << 5) +#define BUS_ERR (0x01 << 6) #define PRE_INF_FRAME_END (0x01 << 8) #define PST_INF_FRAME_END (0x01 << 9) -#define LINE_INT_END (0x1 << 10) +#define LINE_INT_END (0x01 << 10) #define FRAME_END_CLR (0x01 << 0) #define PRE_INF_FRAME_END_CLR (0x01 << 8) #define PST_INF_FRAME_END_CLR (0x01 << 9)