diff options
Diffstat (limited to 'drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c')
| -rw-r--r-- | drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c index e45a213baf49..2311672cedb1 100644 --- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c +++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c @@ -173,7 +173,7 @@ static void rkisp1_gasket_disable(struct rkisp1_device *rkisp1) * or at the frame end interrupt */ static void rkisp1_config_ism(struct rkisp1_isp *isp, - struct v4l2_subdev_state *sd_state) + const struct v4l2_subdev_state *sd_state) { const struct v4l2_rect *src_crop = v4l2_subdev_state_get_crop(sd_state, @@ -201,7 +201,7 @@ static void rkisp1_config_ism(struct rkisp1_isp *isp, * configure ISP blocks with input format, size...... */ static int rkisp1_config_isp(struct rkisp1_isp *isp, - struct v4l2_subdev_state *sd_state, + const struct v4l2_subdev_state *sd_state, enum v4l2_mbus_type mbus_type, u32 mbus_flags) { struct rkisp1_device *rkisp1 = isp->rkisp1; @@ -309,7 +309,7 @@ static int rkisp1_config_isp(struct rkisp1_isp *isp, if (src_fmt->pixel_enc == V4L2_PIXEL_ENC_BAYER) { rkisp1_params_disable(&rkisp1->params); } else { - struct v4l2_mbus_framefmt *src_frm; + const struct v4l2_mbus_framefmt *src_frm; src_frm = v4l2_subdev_state_get_format(sd_state, RKISP1_ISP_PAD_SOURCE_VIDEO); @@ -429,7 +429,7 @@ static void rkisp1_config_clk(struct rkisp1_isp *isp) } static int rkisp1_isp_start(struct rkisp1_isp *isp, - struct v4l2_subdev_state *sd_state, + const struct v4l2_subdev_state *sd_state, struct media_pad *source) { struct rkisp1_device *rkisp1 = isp->rkisp1; @@ -517,6 +517,7 @@ static int rkisp1_isp_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_size_enum *fse) { + struct rkisp1_isp *isp = to_rkisp1_isp(sd); const struct rkisp1_mbus_info *mbus_info; if (fse->pad == RKISP1_ISP_PAD_SINK_PARAMS || @@ -539,9 +540,9 @@ static int rkisp1_isp_enum_frame_size(struct v4l2_subdev *sd, return -EINVAL; fse->min_width = RKISP1_ISP_MIN_WIDTH; - fse->max_width = RKISP1_ISP_MAX_WIDTH; + fse->max_width = isp->rkisp1->info->max_width; fse->min_height = RKISP1_ISP_MIN_HEIGHT; - fse->max_height = RKISP1_ISP_MAX_HEIGHT; + fse->max_height = isp->rkisp1->info->max_height; return 0; } @@ -772,10 +773,10 @@ static void rkisp1_isp_set_sink_fmt(struct rkisp1_isp *isp, sink_fmt->width = clamp_t(u32, format->width, RKISP1_ISP_MIN_WIDTH, - RKISP1_ISP_MAX_WIDTH); + isp->rkisp1->info->max_width); sink_fmt->height = clamp_t(u32, format->height, RKISP1_ISP_MIN_HEIGHT, - RKISP1_ISP_MAX_HEIGHT); + isp->rkisp1->info->max_height); /* * Adjust the color space fields. Accept any color primaries and @@ -880,7 +881,7 @@ static int rkisp1_isp_set_selection(struct v4l2_subdev *sd, if (sel->target != V4L2_SEL_TGT_CROP) return -EINVAL; - dev_dbg(isp->rkisp1->dev, "%s: pad: %d sel(%d,%d)/%dx%d\n", __func__, + dev_dbg(isp->rkisp1->dev, "%s: pad: %d sel(%d,%d)/%ux%u\n", __func__, sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height); if (sel->pad == RKISP1_ISP_PAD_SINK_VIDEO) @@ -935,8 +936,8 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable) sink_pad = &isp->pads[RKISP1_ISP_PAD_SINK_VIDEO]; source_pad = media_pad_remote_pad_unique(sink_pad); if (IS_ERR(source_pad)) { - dev_dbg(rkisp1->dev, "Failed to get source for ISP: %ld\n", - PTR_ERR(source_pad)); + dev_dbg(rkisp1->dev, "Failed to get source for ISP: %pe\n", + source_pad); return -EPIPE; } @@ -964,6 +965,7 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable) } isp->frame_sequence = -1; + isp->frame_active = false; sd_state = v4l2_subdev_lock_and_get_active_state(sd); @@ -1085,12 +1087,15 @@ void rkisp1_isp_unregister(struct rkisp1_device *rkisp1) * Interrupt handlers */ -static void rkisp1_isp_queue_event_sof(struct rkisp1_isp *isp) +static void rkisp1_isp_sof(struct rkisp1_isp *isp) { struct v4l2_event event = { .type = V4L2_EVENT_FRAME_SYNC, }; + isp->frame_sequence++; + isp->frame_active = true; + event.u.frame_sync.frame_sequence = isp->frame_sequence; v4l2_event_queue(isp->sd.devnode, &event); } @@ -1110,15 +1115,20 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx) rkisp1_write(rkisp1, RKISP1_CIF_ISP_ICR, status); - /* Vertical sync signal, starting generating new frame */ - if (status & RKISP1_CIF_ISP_V_START) { - rkisp1->isp.frame_sequence++; - rkisp1_isp_queue_event_sof(&rkisp1->isp); + /* + * Vertical sync signal, starting new frame. Defer handling of vsync + * after RKISP1_CIF_ISP_FRAME if the previous frame was not completed + * yet. + */ + if (status & RKISP1_CIF_ISP_V_START && !rkisp1->isp.frame_active) { + status &= ~RKISP1_CIF_ISP_V_START; + rkisp1_isp_sof(&rkisp1->isp); if (status & RKISP1_CIF_ISP_FRAME) { WARN_ONCE(1, "irq delay is too long, buffers might not be in sync\n"); rkisp1->debug.irq_delay++; } } + if (status & RKISP1_CIF_ISP_PIC_SIZE_ERROR) { /* Clear pic_size_error */ isp_err = rkisp1_read(rkisp1, RKISP1_CIF_ISP_ERR); @@ -1137,6 +1147,7 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx) if (status & RKISP1_CIF_ISP_FRAME) { u32 isp_ris; + rkisp1->isp.frame_active = false; rkisp1->debug.complete_frames++; /* New frame from the sensor received */ @@ -1151,5 +1162,12 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx) rkisp1_params_isr(rkisp1); } + /* + * Deferred handling of vsync if RKISP1_CIF_ISP_V_START and + * RKISP1_CIF_ISP_FRAME occurred in the same irq. + */ + if (status & RKISP1_CIF_ISP_V_START) + rkisp1_isp_sof(&rkisp1->isp); + return IRQ_HANDLED; } |
