int rkisp1_csi_link_sensor(struct rkisp1_device *rkisp1, struct v4l2_subdev *sd, struct rkisp1_sensor_async *s_asd, unsignedint source_pad)
{ struct rkisp1_csi *csi = &rkisp1->csi; int ret;
s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler,
V4L2_CID_PIXEL_RATE); if (!s_asd->pixel_rate_ctrl) {
dev_err(rkisp1->dev, "No pixel rate control in subdev %s\n",
sd->name); return -EINVAL;
}
/* Create the link from the sensor to the CSI receiver. */
ret = media_create_pad_link(&sd->entity, source_pad,
&csi->sd.entity, RKISP1_CSI_PAD_SINK,
!s_asd->index ? MEDIA_LNK_FL_ENABLED : 0); if (ret) {
dev_err(csi->rkisp1->dev, "failed to link src pad of %s\n",
sd->name); return ret;
}
/* V12 could also use a newer csi2-host, but we don't want that yet */ if (rkisp1->info->isp_ver == RKISP1_V12)
rkisp1_write(rkisp1, RKISP1_CIF_ISP_CSI0_CTRL0, 0);
/* Configure Data Type and Virtual Channel */
rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL,
RKISP1_CIF_MIPI_DATA_SEL_DT(format->mipi_dt) |
RKISP1_CIF_MIPI_DATA_SEL_VC(0));
/* * Disable RKISP1_CIF_MIPI_ERR_DPHY interrupt here temporary for * isp bus may be dead when switch isp.
*/
rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC,
RKISP1_CIF_MIPI_FRAME_END | RKISP1_CIF_MIPI_ERR_CSI |
RKISP1_CIF_MIPI_ERR_DPHY |
RKISP1_CIF_MIPI_SYNC_FIFO_OVFLW(0x03) |
RKISP1_CIF_MIPI_ADD_DATA_OVFLW);
/* * Wait until the IRQ handler has ended. The IRQ handler may get called * even after this, but it will return immediately as the MIPI * interrupts have been masked.
*/
synchronize_irq(rkisp1->irqs[RKISP1_IRQ_MIPI]);
/* Clear MIPI interrupt status */
rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, ~0);
val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL);
rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL,
val & (~RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA));
}
/* * Disable DPHY errctrl interrupt, because this dphy * erctrl signal is asserted until the next changes * of line state. This time is may be too long and cpu * is hold in this interrupt.
*/ if (status & RKISP1_CIF_MIPI_ERR_CTRL(0x0f)) {
val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC,
val & ~RKISP1_CIF_MIPI_ERR_CTRL(0x0f));
rkisp1->csi.is_dphy_errctrl_disabled = true;
}
/* * Enable DPHY errctrl interrupt again, if mipi have receive * the whole frame without any error.
*/ if (status == RKISP1_CIF_MIPI_FRAME_END) { /* * Enable DPHY errctrl interrupt again, if mipi have receive * the whole frame without any error.
*/ if (rkisp1->csi.is_dphy_errctrl_disabled) {
val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC);
val |= RKISP1_CIF_MIPI_ERR_CTRL(0x0f);
rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, val);
rkisp1->csi.is_dphy_errctrl_disabled = false;
}
} else {
rkisp1->debug.mipi_error++;
}
return IRQ_HANDLED;
}
/* ---------------------------------------------------------------------------- * Subdev pad operations
*/
if (!enable) {
v4l2_subdev_call(csi->source, video, s_stream, false);
rkisp1_csi_stop(csi);
return 0;
}
source_pad = media_entity_remote_source_pad_unique(&sd->entity); if (IS_ERR(source_pad)) {
dev_dbg(rkisp1->dev, "Failed to get source for CSI: %ld\n",
PTR_ERR(source_pad)); return -EPIPE;
}
source = media_entity_to_v4l2_subdev(source_pad->entity); if (!source) { /* This should really not happen, so is not worth a message. */ return -EPIPE;
}
asc = v4l2_async_connection_unique(source); if (!asc) return -EPIPE;
int rkisp1_csi_init(struct rkisp1_device *rkisp1)
{ struct rkisp1_csi *csi = &rkisp1->csi;
csi->rkisp1 = rkisp1;
csi->dphy = devm_phy_get(rkisp1->dev, "dphy"); if (IS_ERR(csi->dphy)) return dev_err_probe(rkisp1->dev, PTR_ERR(csi->dphy), "Couldn't get the MIPI D-PHY\n");
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.