/* * NOTE: MIPI controller and input MUX are also configured in this file. * This is because ISP Subdev describes not only ISP submodule (input size, * format, output size, format), but also a virtual route device.
*/
/* * There are many variables named with format/frame in below code, * please see here for their meaning. * Cropping in the sink pad defines the image region from the sensor. * Cropping in the source pad defines the region for the Image Stabilizer (IS) * * Cropping regions of ISP * * +---------------------------------------------------------+ * | Sensor image | * | +---------------------------------------------------+ | * | | CIF_ISP_ACQ (for black level) | | * | | sink pad format | | * | | +--------------------------------------------+ | | * | | | CIF_ISP_OUT | | | * | | | sink pad crop | | | * | | | +---------------------------------+ | | | * | | | | CIF_ISP_IS | | | | * | | | | source pad crop and format | | | | * | | | +---------------------------------+ | | | * | | +--------------------------------------------+ | | * | +---------------------------------------------------+ | * +---------------------------------------------------------+
*/
/* ----------------------------------------------------------------------------- * Media block control (i.MX8MP only)
*/
/* * Configure and enable the gasket with the CSI-2 data type. Set the * vsync polarity as active high, as that is what the ISP is configured * to expect in ISP_ACQ_PROP. Enable left justification, as the i.MX8MP * ISP has a 16-bit wide input and expects data to be left-aligned.
*/
source_sd = media_entity_to_v4l2_subdev(source->entity);
ret = v4l2_subdev_call(source_sd, pad, get_frame_desc,
source->index, &fd); if (ret) {
dev_err(rkisp1->dev, "failed to get frame descriptor from '%s':%u: %d\n",
source_sd->name, 0, ret); return ret;
}
if (fd.num_entries != 1) {
dev_err(rkisp1->dev, "invalid frame descriptor for '%s':%u\n",
source_sd->name, 0); return -EINVAL;
}
/* ---------------------------------------------------------------------------- * Camera Interface registers configurations
*/
/* * Image Stabilization. * This should only be called when configuring CIF * or at the frame end interrupt
*/ staticvoid rkisp1_config_ism(struct rkisp1_isp *isp, conststruct v4l2_subdev_state *sd_state)
{ conststruct v4l2_rect *src_crop =
v4l2_subdev_state_get_crop(sd_state,
RKISP1_ISP_PAD_SOURCE_VIDEO); struct rkisp1_device *rkisp1 = isp->rkisp1;
u32 val;
/* IS(Image Stabilization) is always on, working as output crop */
rkisp1_write(rkisp1, RKISP1_CIF_ISP_IS_CTRL, 1);
val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL);
val |= RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD;
rkisp1_write(rkisp1, RKISP1_CIF_ISP_CTRL, val);
}
/* * Wait until the IRQ handler has ended. The IRQ handler may get called * even after this, but it will return immediately as the MI and ISP * interrupts have been masked.
*/
synchronize_irq(rkisp1->irqs[RKISP1_IRQ_ISP]); if (rkisp1->irqs[RKISP1_IRQ_ISP] != rkisp1->irqs[RKISP1_IRQ_MI])
synchronize_irq(rkisp1->irqs[RKISP1_IRQ_MI]);
/* Clear MI and ISP interrupt status */
rkisp1_write(rkisp1, RKISP1_CIF_ISP_ICR, ~0);
rkisp1_write(rkisp1, RKISP1_CIF_MI_ICR, ~0);
/* stop ISP */
val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL);
val &= ~(RKISP1_CIF_ISP_CTRL_ISP_INFORM_ENABLE |
RKISP1_CIF_ISP_CTRL_ISP_ENABLE);
rkisp1_write(rkisp1, RKISP1_CIF_ISP_CTRL, val);
val = rkisp1_read(rkisp1, RKISP1_CIF_ISP_CTRL);
rkisp1_write(rkisp1, RKISP1_CIF_ISP_CTRL,
val | RKISP1_CIF_ISP_CTRL_ISP_CFG_UPD);
/* ensure sp and mp can run at the same time in V12 */ if (rkisp1->info->isp_ver == RKISP1_V12) {
val = RKISP1_CIF_CLK_CTRL_MI_Y12 | RKISP1_CIF_CLK_CTRL_MI_SP |
RKISP1_CIF_CLK_CTRL_MI_RAW0 | RKISP1_CIF_CLK_CTRL_MI_RAW1 |
RKISP1_CIF_CLK_CTRL_MI_READ | RKISP1_CIF_CLK_CTRL_MI_RAWRD |
RKISP1_CIF_CLK_CTRL_CP | RKISP1_CIF_CLK_CTRL_IE;
rkisp1_write(rkisp1, RKISP1_CIF_VI_ISP_CLK_CTRL_V12, val);
}
}
/* * Media bus code. The ISP can operate in pass-through mode (Bayer in, * Bayer out or YUV in, YUV out) or process Bayer data to YUV, but * can't convert from YUV to Bayer.
*/
sink_info = rkisp1_mbus_info_get_by_code(sink_fmt->code);
/* * The source width and height must be identical to the source crop * size.
*/
src_fmt->width = src_crop->width;
src_fmt->height = src_crop->height;
/* * Copy the color space for the sink pad. When converting from Bayer to * YUV, default to a limited quantization range.
*/
src_fmt->colorspace = sink_fmt->colorspace;
src_fmt->xfer_func = sink_fmt->xfer_func;
src_fmt->ycbcr_enc = sink_fmt->ycbcr_enc;
/* * Allow setting the source color space fields when the SET_CSC flag is * set and the source format is YUV. If the sink format is YUV, don't * set the color primaries, transfer function or YCbCr encoding as the * ISP is bypassed in that case and passes YUV data through without * modifications. * * The color primaries and transfer function are configured through the * cross-talk matrix and tone curve respectively. Settings for those * hardware blocks are conveyed through the ISP parameters buffer, as * they need to combine color space information with other image tuning * characteristics and can't thus be computed by the kernel based on the * color space. The source pad colorspace and xfer_func fields are thus * ignored by the driver, but can be set by userspace to propagate * accurate color space information down the pipeline.
*/
set_csc = format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC;
if (set_csc && src_info->pixel_enc == V4L2_PIXEL_ENC_YUV) { if (sink_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) { if (format->colorspace != V4L2_COLORSPACE_DEFAULT)
src_fmt->colorspace = format->colorspace; if (format->xfer_func != V4L2_XFER_FUNC_DEFAULT)
src_fmt->xfer_func = format->xfer_func; if (format->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT)
src_fmt->ycbcr_enc = format->ycbcr_enc;
}
if (format->quantization != V4L2_QUANTIZATION_DEFAULT)
src_fmt->quantization = format->quantization;
}
*format = *src_fmt;
/* * Restore the SET_CSC flag if it was set to indicate support for the * CSC setting API.
*/ if (set_csc)
format->flags |= V4L2_MBUS_FRAMEFMT_SET_CSC;
}
/* Propagate to out format */
src_fmt = v4l2_subdev_state_get_format(sd_state,
RKISP1_ISP_PAD_SOURCE_VIDEO);
rkisp1_isp_set_src_fmt(isp, sd_state, src_fmt);
}
/* * Adjust the color space fields. Accept any color primaries and * transfer function for both YUV and Bayer. For YUV any YCbCr encoding * and quantization range is also accepted. For Bayer formats, the YCbCr * encoding isn't applicable, and the quantization range can only be * full.
*/
is_yuv = mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV;
sink_fmt->colorspace = format->colorspace ? :
(is_yuv ? V4L2_COLORSPACE_SRGB :
V4L2_COLORSPACE_RAW);
sink_fmt->xfer_func = format->xfer_func ? :
V4L2_MAP_XFER_FUNC_DEFAULT(sink_fmt->colorspace); if (is_yuv) {
sink_fmt->ycbcr_enc = format->ycbcr_enc ? :
V4L2_MAP_YCBCR_ENC_DEFAULT(sink_fmt->colorspace);
sink_fmt->quantization = format->quantization ? :
V4L2_MAP_QUANTIZATION_DEFAULT(false, sink_fmt->colorspace,
sink_fmt->ycbcr_enc);
} else { /* * The YCbCr encoding isn't applicable for non-YUV formats, but * V4L2 has no "no encoding" value. Hardcode it to Rec. 601, it * should be ignored by userspace.
*/
sink_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
sink_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
}
*format = *sink_fmt;
/* Propagate to in crop */
sink_crop = v4l2_subdev_state_get_crop(sd_state,
RKISP1_ISP_PAD_SINK_VIDEO);
rkisp1_isp_set_sink_crop(isp, sd_state, sink_crop);
}
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)); return -EPIPE;
}
rkisp1->source = media_entity_to_v4l2_subdev(source_pad->entity); if (!rkisp1->source) { /* This should really not happen, so is not worth a message. */ return -EPIPE;
}
status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS); if (!status) return IRQ_NONE;
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); 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); if (isp_err & RKISP1_CIF_ISP_ERR_INFORM_SIZE)
rkisp1->debug.inform_size_error++; if (isp_err & RKISP1_CIF_ISP_ERR_IS_SIZE)
rkisp1->debug.img_stabilization_size_error++; if (isp_err & RKISP1_CIF_ISP_ERR_OUTFORM_SIZE)
rkisp1->debug.outform_size_error++;
rkisp1_write(rkisp1, RKISP1_CIF_ISP_ERR_CLR, isp_err);
} elseif (status & RKISP1_CIF_ISP_DATA_LOSS) { /* keep track of data_loss in debugfs */
rkisp1->debug.data_loss++;
}
if (status & RKISP1_CIF_ISP_FRAME) {
u32 isp_ris;
rkisp1->debug.complete_frames++;
/* New frame from the sensor received */
isp_ris = rkisp1_read(rkisp1, RKISP1_CIF_ISP_RIS); if (isp_ris & RKISP1_STATS_MEAS_MASK)
rkisp1_stats_isr(&rkisp1->stats, isp_ris); /* * Then update changed configs. Some of them involve * lot of register writes. Do those only one per frame. * Do the updates in the order of the processing flow.
*/
rkisp1_params_isr(rkisp1);
}
return IRQ_HANDLED;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.3 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.