/* * vsp1_create_sink_links - Create links from all sources to the given sink * * This function creates media links from all valid sources to the given sink * pad. Links that would be invalid according to the VSP1 hardware capabilities * are skipped. Those include all links * * - from a UDS to a UDS (UDS entities can't be chained) * - from an entity to itself (no loops are allowed) * * Furthermore, the BRS can't be connected to histogram generators, but no * special check is currently needed as all VSP instances that include a BRS * have no histogram generator.
*/ staticint vsp1_create_sink_links(struct vsp1_device *vsp1, struct vsp1_entity *sink)
{ struct media_entity *entity = &sink->subdev.entity; struct vsp1_entity *source; unsignedint pad; int ret;
ret = vsp1_create_sink_links(vsp1, entity); if (ret < 0) return ret;
}
if (vsp1->hgo) {
ret = media_create_pad_link(&vsp1->hgo->histo.entity.subdev.entity,
HISTO_PAD_SOURCE,
&vsp1->hgo->histo.video.entity, 0,
MEDIA_LNK_FL_ENABLED |
MEDIA_LNK_FL_IMMUTABLE); if (ret < 0) return ret;
}
if (vsp1->hgt) {
ret = media_create_pad_link(&vsp1->hgt->histo.entity.subdev.entity,
HISTO_PAD_SOURCE,
&vsp1->hgt->histo.video.entity, 0,
MEDIA_LNK_FL_ENABLED |
MEDIA_LNK_FL_IMMUTABLE); if (ret < 0) return ret;
}
for (i = 0; i < vsp1->info->lif_count; ++i) { if (!vsp1->lif[i]) continue;
ret = media_create_pad_link(&vsp1->wpf[i]->entity.subdev.entity,
RWPF_PAD_SOURCE,
&vsp1->lif[i]->entity.subdev.entity,
LIF_PAD_SINK, 0); if (ret < 0) return ret;
}
for (i = 0; i < vsp1->info->rpf_count; ++i) { struct vsp1_rwpf *rpf = vsp1->rpf[i];
ret = media_create_pad_link(&rpf->video->video.entity, 0,
&rpf->entity.subdev.entity,
RWPF_PAD_SINK,
MEDIA_LNK_FL_ENABLED |
MEDIA_LNK_FL_IMMUTABLE); if (ret < 0) return ret;
}
for (i = 0; i < vsp1->info->wpf_count; ++i) { /* * Connect the video device to the WPF. All connections are * immutable.
*/ struct vsp1_rwpf *wpf = vsp1->wpf[i];
ret = media_create_pad_link(&wpf->entity.subdev.entity,
RWPF_PAD_SOURCE,
&wpf->video->video.entity, 0,
MEDIA_LNK_FL_IMMUTABLE |
MEDIA_LNK_FL_ENABLED); if (ret < 0) return ret;
}
vsp1->media_ops.link_setup = vsp1_entity_link_setup; /* * Don't perform link validation when the userspace API is disabled as * the pipeline is configured internally by the driver in that case, and * its configuration can thus be trusted.
*/ if (vsp1->info->uapi)
vsp1->media_ops.link_validate = v4l2_subdev_link_validate;
/* Instantiate all the entities. */ if (vsp1_feature(vsp1, VSP1_HAS_BRS)) {
vsp1->brs = vsp1_brx_create(vsp1, VSP1_ENTITY_BRS); if (IS_ERR(vsp1->brs)) {
ret = PTR_ERR(vsp1->brs); goto done;
}
/* * The LIFs are only supported when used in conjunction with the DU, in * which case the userspace API is disabled. If the userspace API is * enabled skip the LIFs, even when present.
*/ if (!vsp1->info->uapi) { for (i = 0; i < vsp1->info->lif_count; ++i) { struct vsp1_lif *lif;
lif = vsp1_lif_create(vsp1, i); if (IS_ERR(lif)) {
ret = PTR_ERR(lif); goto done;
}
if (vsp1->info->uapi) { struct vsp1_video *video = vsp1_video_create(vsp1, wpf);
if (IS_ERR(video)) {
ret = PTR_ERR(video); goto done;
}
list_add_tail(&video->list, &vsp1->videos);
}
}
/* Register all subdevs. */
list_for_each_entry(entity, &vsp1->entities, list_dev) {
ret = v4l2_device_register_subdev(&vsp1->v4l2_dev,
&entity->subdev); if (ret < 0) goto done;
}
/* * Create links and register subdev nodes if the userspace API is * enabled or initialize the DRM pipeline otherwise.
*/ if (vsp1->info->uapi) {
ret = vsp1_uapi_create_links(vsp1); if (ret < 0) goto done;
ret = v4l2_device_register_subdev_nodes(&vsp1->v4l2_dev); if (ret < 0) goto done;
ret = media_device_register(mdev);
} else { if (vsp1->info->version == VI6_IP_VERSION_MODEL_VSPX_GEN4)
ret = vsp1_vspx_init(vsp1); else
ret = vsp1_drm_init(vsp1);
}
done: if (ret < 0)
vsp1_destroy_entities(vsp1);
return ret;
}
int vsp1_reset_wpf(struct vsp1_device *vsp1, unsignedint index)
{
u32 version = vsp1->version & VI6_IP_VERSION_MODEL_MASK; unsignedint timeout; int ret = 0;
u32 status;
status = vsp1_read(vsp1, VI6_STATUS); if (!(status & VI6_STATUS_SYS_ACT(index))) return 0;
vsp1_write(vsp1, VI6_SRESET, VI6_SRESET_SRTS(index)); for (timeout = 10; timeout > 0; --timeout) {
status = vsp1_read(vsp1, VI6_STATUS); if (!(status & VI6_STATUS_SYS_ACT(index))) break;
usleep_range(1000, 2000);
}
if (!timeout) {
dev_err(vsp1->dev, "failed to reset wpf.%u\n", index); return -ETIMEDOUT;
}
if (version == VI6_IP_VERSION_MODEL_VSPD_GEN3 ||
version == VI6_IP_VERSION_MODEL_VSPD_GEN4)
ret = rcar_fcp_soft_reset(vsp1->fcp);
return ret;
}
staticint vsp1_device_init(struct vsp1_device *vsp1)
{ unsignedint i; int ret;
/* Reset any channel that might be running. */ for (i = 0; i < vsp1->info->wpf_count; ++i) {
ret = vsp1_reset_wpf(vsp1, i); if (ret < 0) return ret;
}
for (i = 0; i < vsp1->info->lif_count; ++i)
vsp1_write(vsp1, VI6_DISP_IRQ_ENB(i), 0); for (i = 0; i < vsp1->info->wpf_count; ++i)
vsp1_write(vsp1, VI6_WPF_IRQ_ENB(i), 0);
}
/* * vsp1_device_get - Acquire the VSP1 device * * Make sure the device is not suspended and initialize it if needed. * * Return 0 on success or a negative error code otherwise.
*/ int vsp1_device_get(struct vsp1_device *vsp1)
{ return pm_runtime_resume_and_get(vsp1->dev);
}
/* * vsp1_device_put - Release the VSP1 device * * Decrement the VSP1 reference count and cleanup the device if the last * reference is released.
*/ void vsp1_device_put(struct vsp1_device *vsp1)
{
pm_runtime_put_sync(vsp1->dev);
}
/* ----------------------------------------------------------------------------- * Power Management
*/
ret = reset_control_deassert(vsp1->rstc); if (ret < 0) return ret;
if (vsp1->info) { /* * On R-Car Gen2 and RZ/G1, vsp1 register access after deassert * can cause lock-up. It is a special case and needs some delay * to avoid this lock-up.
*/ if (vsp1->info->gen == 2)
udelay(1);
ret = vsp1_device_init(vsp1); if (ret < 0) goto done;
}
ret = rcar_fcp_enable(vsp1->fcp);
done: if (ret < 0)
reset_control_assert(vsp1->rstc);
/* * Try the info stored in match data first for devices that don't have * a version register.
*/
info = of_device_get_match_data(vsp1->dev); if (info) {
vsp1->version = VI6_IP_VERSION_VSP_SW | info->version | info->soc; return info;
}
/* I/O and IRQ resources (clock managed by the clock PM domain). */
vsp1->mmio = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(vsp1->mmio)) return PTR_ERR(vsp1->mmio);
irq = platform_get_irq(pdev, 0); if (irq < 0) return irq;
vsp1->rstc = devm_reset_control_get_shared(&pdev->dev, NULL); if (IS_ERR(vsp1->rstc)) return dev_err_probe(&pdev->dev, PTR_ERR(vsp1->rstc), "failed to get reset control\n");
/* FCP (optional). */
fcp_node = of_parse_phandle(pdev->dev.of_node, "renesas,fcp", 0); if (fcp_node) {
vsp1->fcp = rcar_fcp_get(fcp_node);
of_node_put(fcp_node); if (IS_ERR(vsp1->fcp)) {
dev_dbg(&pdev->dev, "FCP not found (%ld)\n",
PTR_ERR(vsp1->fcp)); return PTR_ERR(vsp1->fcp);
}
/* * When the FCP is present, it handles all bus master accesses * for the VSP and must thus be used in place of the VSP device * to map DMA buffers.
*/
vsp1->bus_master = rcar_fcp_get_device(vsp1->fcp);
} else {
vsp1->bus_master = vsp1->dev;
}
/* Configure device parameters based on the version register. */
pm_runtime_enable(&pdev->dev);
ret = vsp1_device_get(vsp1); if (ret < 0) goto done;
vsp1->info = vsp1_lookup_info(vsp1); if (!vsp1->info) {
vsp1_device_put(vsp1);
ret = -ENXIO; goto done;
}
dev_dbg(&pdev->dev, "IP version 0x%08x\n", vsp1->version);
/* * Previous use of the hardware (e.g. by the bootloader) could leave * some interrupts enabled and pending. * * TODO: Investigate if this shouldn't be better handled by using the * device reset provided by the CPG.
*/
vsp1_mask_all_interrupts(vsp1);
vsp1_device_put(vsp1);
ret = devm_request_irq(&pdev->dev, irq, vsp1_irq_handler,
IRQF_SHARED, dev_name(&pdev->dev), vsp1); if (ret < 0) {
dev_err(&pdev->dev, "failed to request IRQ\n"); goto done;
}
/* Instantiate entities. */
ret = vsp1_create_entities(vsp1); if (ret < 0) {
dev_err(&pdev->dev, "failed to create entities\n"); goto done;
}
done: if (ret) {
pm_runtime_disable(&pdev->dev);
rcar_fcp_put(vsp1->fcp);
}
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.