/** * DOC: Video Processing Unit * * VPU Handles the Global Video Processing, it includes management of the * clocks gates, blocks reset lines and power domains. * * What is missing : * * - Full reset of entire video processing HW blocks * - Scaling and setup of the VPU clock * - Bus clock gates * - Powering up video processing HW blocks * - Powering Up HDMI controller and PHY
*/
/* Parses each endpoint and check if remote exists */
for_each_endpoint_of_node(dev->of_node, ep) { /* If the endpoint node exists, consider it enabled */
remote = of_graph_get_remote_port(ep); if (remote) {
of_node_put(remote);
of_node_put(ep); returntrue;
}
}
/* * Slave dc0 and dc5 connected to master port 1. * By default other slaves are connected to master port 0.
*/
value = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1) |
VPU_RDARB_SLAVE_TO_MASTER_PORT(5, 1);
writel_relaxed(value, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
/* Slave dc0 connected to master port 1 */
value = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1);
writel_relaxed(value, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
/* Slave dc4 and dc7 connected to master port 1 */
value = VPU_RDARB_SLAVE_TO_MASTER_PORT(4, 1) |
VPU_RDARB_SLAVE_TO_MASTER_PORT(7, 1);
writel_relaxed(value, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
/* Slave dc1 connected to master port 1 */
value = VPU_RDARB_SLAVE_TO_MASTER_PORT(1, 1);
writel_relaxed(value, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
}
/* Checks if an output connector is available */ if (!meson_vpu_has_available_connectors(dev)) {
dev_err(dev, "No output connector available\n"); return -ENODEV;
}
match = of_device_get_match_data(dev); if (!match) return -ENODEV;
drm = drm_dev_alloc(&meson_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm);
regs = devm_platform_ioremap_resource_byname(pdev, "vpu"); if (IS_ERR(regs)) {
ret = PTR_ERR(regs); goto free_drm;
}
priv->io_base = regs;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hhi"); if (!res) {
ret = -EINVAL; goto free_drm;
} /* Simply ioremap since it may be a shared register zone */
regs = devm_ioremap(dev, res->start, resource_size(res)); if (!regs) {
ret = -EADDRNOTAVAIL; goto free_drm;
}
priv->hhi = devm_regmap_init_mmio(dev, regs,
&meson_regmap_config); if (IS_ERR(priv->hhi)) {
dev_err(&pdev->dev, "Couldn't create the HHI regmap\n");
ret = PTR_ERR(priv->hhi); goto free_drm;
}
priv->canvas = meson_canvas_get(dev); if (IS_ERR(priv->canvas)) {
ret = PTR_ERR(priv->canvas); goto free_drm;
}
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_osd1); if (ret) goto free_drm;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0); if (ret) goto free_canvas_osd1;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_1); if (ret) goto free_canvas_vd1_0;
ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_2); if (ret) goto free_canvas_vd1_1;
priv->vsync_irq = platform_get_irq(pdev, 0);
ret = drm_vblank_init(drm, 1); if (ret) goto free_canvas_vd1_2;
/* Assign limits per soc revision/package */ for (i = 0 ; i < ARRAY_SIZE(meson_drm_soc_attrs) ; ++i) { if (soc_device_match(meson_drm_soc_attrs[i].attrs)) {
priv->limits = &meson_drm_soc_attrs[i].limits; break;
}
}
/* * Remove early framebuffers (ie. simplefb). The framebuffer can be * located anywhere in RAM
*/
ret = aperture_remove_all_conflicting_devices(meson_driver.name); if (ret) goto free_canvas_vd1_2;
ret = drmm_mode_config_init(drm); if (ret) goto free_canvas_vd1_2;
drm->mode_config.max_width = 3840;
drm->mode_config.max_height = 2160;
drm->mode_config.funcs = &meson_mode_config_funcs;
drm->mode_config.helper_private = &meson_mode_config_helpers;
/* Hardware Initialization */
meson_vpu_init(priv);
meson_venc_init(priv);
meson_vpp_init(priv);
meson_viu_init(priv); if (priv->afbcd.ops) {
ret = priv->afbcd.ops->init(priv); if (ret) goto free_canvas_vd1_2;
}
/* Encoder Initialization */
ret = meson_encoder_cvbs_probe(priv); if (ret) goto exit_afbcd;
if (has_components) {
ret = component_bind_all(dev, drm); if (ret) {
dev_err(drm->dev, "Couldn't bind all components\n"); /* Do not try to unbind */
has_components = false; goto exit_afbcd;
}
}
ret = meson_encoder_hdmi_probe(priv); if (ret) goto exit_afbcd;
if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
ret = meson_encoder_dsi_probe(priv); if (ret) goto exit_afbcd;
}
ret = meson_plane_create(priv); if (ret) goto exit_afbcd;
ret = meson_overlay_create(priv); if (ret) goto exit_afbcd;
ret = meson_crtc_create(priv); if (ret) goto exit_afbcd;
ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm); if (ret) goto exit_afbcd;
drm_mode_config_reset(drm);
drm_kms_helper_poll_init(drm);
platform_set_drvdata(pdev, priv);
ret = drm_dev_register(drm, 0); if (ret) goto uninstall_irq;
/* * Only devices to use as components * TOFIX: get rid of components when we can finally * get meson_dx_hdmi to stop using the meson_drm * private structure for HHI registers.
*/ staticconststruct of_device_id components_dev_match[] = {
{ .compatible = "amlogic,meson-gxbb-dw-hdmi" },
{ .compatible = "amlogic,meson-gxl-dw-hdmi" },
{ .compatible = "amlogic,meson-gxm-dw-hdmi" },
{ .compatible = "amlogic,meson-g12a-dw-hdmi" },
{}
};
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.