#ifdefined CONFIG_OF && defined CONFIG_COMMON_CLK /* * Clock handling code. * * Here we handle the clocks property of our "simple-framebuffer" dt node. * This is necessary so that we can make sure that any clocks needed by * the display engine that the bootloader set up for us (and for which it * provided a simplefb dt node), stay up, for the life of the simplefb * driver. * * When the driver unloads, we cleanly disable, and then release the clocks. * * We only complain about errors here, no action is taken as the most likely * error can only happen due to a mismatch between the bootloader which set * up simplefb, and the clock definitions in the device tree. Chances are * that there are no adverse effects, and if there are, a clean teardown of * the fb probe will not help us much either. So just complain and carry on, * and hope that the user actually gets a working fb at the end of things.
*/
for (i = 0; i < sdev->clk_count; ++i) {
clock = of_clk_get(of_node, i); if (IS_ERR(clock)) {
ret = PTR_ERR(clock); if (ret == -EPROBE_DEFER) goto err;
drm_err(dev, "clock %u not found: %d\n", i, ret); continue;
}
ret = clk_prepare_enable(clock); if (ret) {
drm_err(dev, "failed to enable clock %u: %d\n",
i, ret);
clk_put(clock); continue;
}
sdev->clks[i] = clock;
}
/* * Regulator handling code. * * Here we handle the num-supplies and vin*-supply properties of our * "simple-framebuffer" dt node. This is necessary so that we can make sure * that any regulators needed by the display hardware that the bootloader * set up for us (and for which it provided a simplefb dt node), stay up, * for the life of the simplefb driver. * * When the driver unloads, we cleanly disable, and then release the * regulators. * * We only complain about errors here, no action is taken as the most likely * error can only happen due to a mismatch between the bootloader which set * up simplefb, and the regulator definitions in the device tree. Chances are * that there are no adverse effects, and if there are, a clean teardown of * the fb probe will not help us much either. So just complain and carry on, * and hope that the user actually gets a working fb at the end of things.
*/
for (i = 0; i < sdev->regulator_count; ++i) { if (sdev->regulators[i]) {
regulator_disable(sdev->regulators[i]);
regulator_put(sdev->regulators[i]);
}
}
}
if (dev_get_platdata(&pdev->dev) || !of_node) return 0;
/* Count the number of regulator supplies */
for_each_property_of_node(of_node, prop) {
p = strstr(prop->name, SUPPLY_SUFFIX); if (p && p != prop->name)
++count;
}
#ifdefined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS /* * Generic power domain handling code. * * Here we handle the power-domains properties of our "simple-framebuffer" * dt node. This is only necessary if there is more than one power-domain. * A single power-domains is handled automatically by the driver core. Multiple * power-domains have to be handled by drivers since the driver core can't know * the correct power sequencing. Power sequencing is not an issue for simpledrm * since the bootloader has put the power domains already in the correct state. * simpledrm has only to ensure they remain active for its lifetime. * * When the driver unloads, we detach from the power-domains. * * We only complain about errors here, no action is taken as the most likely * error can only happen due to a mismatch between the bootloader which set * up the "simple-framebuffer" dt node, and the PM domain providers in the * device tree. Chances are that there are no adverse effects, and if there are, * a clean teardown of the fb probe will not help us much either. So just * complain and carry on, and hope that the user actually gets a working fb at * the end of things.
*/ staticvoid simpledrm_device_detach_genpd(void *res)
{ int i; struct simpledrm_device *sdev = res;
if (sdev->pwr_dom_count <= 1) return;
for (i = sdev->pwr_dom_count - 1; i >= 0; i--) { if (sdev->pwr_dom_links[i])
device_link_del(sdev->pwr_dom_links[i]); if (!IS_ERR_OR_NULL(sdev->pwr_dom_devs[i]))
dev_pm_domain_detach(sdev->pwr_dom_devs[i], true);
}
}
sdev->pwr_dom_count = of_count_phandle_with_args(dev->of_node, "power-domains", "#power-domain-cells"); /* * Single power-domain devices are handled by driver core nothing to do * here. The same for device nodes without "power-domains" property.
*/ if (sdev->pwr_dom_count <= 1) return 0;
sdev->pwr_dom_devs = devm_kcalloc(dev, sdev->pwr_dom_count, sizeof(*sdev->pwr_dom_devs),
GFP_KERNEL); if (!sdev->pwr_dom_devs) return -ENOMEM;
sdev->pwr_dom_links = devm_kcalloc(dev, sdev->pwr_dom_count, sizeof(*sdev->pwr_dom_links),
GFP_KERNEL); if (!sdev->pwr_dom_links) return -ENOMEM;
for (i = 0; i < sdev->pwr_dom_count; i++) {
sdev->pwr_dom_devs[i] = dev_pm_domain_attach_by_id(dev, i); if (IS_ERR(sdev->pwr_dom_devs[i])) { int ret = PTR_ERR(sdev->pwr_dom_devs[i]); if (ret == -EPROBE_DEFER) {
simpledrm_device_detach_genpd(sdev); return ret;
}
drm_warn(&sdev->sysfb.dev, "pm_domain_attach_by_id(%u) failed: %d\n", i, ret); continue;
}
sdev->pwr_dom_links[i] = device_link_add(dev,
sdev->pwr_dom_devs[i],
DL_FLAG_STATELESS |
DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE); if (!sdev->pwr_dom_links[i])
drm_warn(&sdev->sysfb.dev, "failed to link power-domain %d\n", i);
}
sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device, sysfb.dev); if (IS_ERR(sdev)) return ERR_CAST(sdev);
sysfb = &sdev->sysfb;
dev = &sysfb->dev;
platform_set_drvdata(pdev, sdev);
/* * Hardware settings
*/
ret = simpledrm_device_init_clocks(sdev); if (ret) return ERR_PTR(ret);
ret = simpledrm_device_init_regulators(sdev); if (ret) return ERR_PTR(ret);
ret = simpledrm_device_attach_genpd(sdev); if (ret) return ERR_PTR(ret);
if (pd) {
width = simplefb_get_width_pd(dev, pd); if (width < 0) return ERR_PTR(width);
height = simplefb_get_height_pd(dev, pd); if (height < 0) return ERR_PTR(height);
stride = simplefb_get_stride_pd(dev, pd); if (stride < 0) return ERR_PTR(stride);
format = simplefb_get_format_pd(dev, pd); if (IS_ERR(format)) return ERR_CAST(format);
} elseif (of_node) {
width = simplefb_get_width_of(dev, of_node); if (width < 0) return ERR_PTR(width);
height = simplefb_get_height_of(dev, of_node); if (height < 0) return ERR_PTR(height);
stride = simplefb_get_stride_of(dev, of_node); if (stride < 0) return ERR_PTR(stride);
format = simplefb_get_format_of(dev, of_node); if (IS_ERR(format)) return ERR_CAST(format);
mem = simplefb_get_memory_of(dev, of_node); if (IS_ERR(mem)) return ERR_CAST(mem);
panel_node = of_parse_phandle(of_node, "panel", 0); if (panel_node) {
simplefb_read_u32_of(dev, panel_node, "width-mm", &width_mm);
simplefb_read_u32_of(dev, panel_node, "height-mm", &height_mm);
of_node_put(panel_node);
}
} else {
drm_err(dev, "no simplefb configuration found\n"); return ERR_PTR(-ENODEV);
} if (!stride) {
stride = drm_format_info_min_pitch(format, 0, width); if (drm_WARN_ON(dev, !stride)) return ERR_PTR(-EINVAL);
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return ERR_PTR(-EINVAL);
ret = devm_aperture_acquire_for_platform_device(pdev, res->start,
resource_size(res)); if (ret) {
drm_err(dev, "could not acquire memory range %pr: %d\n", res, ret); return ERR_PTR(ret);
}
drm_dbg(dev, "using I/O memory framebuffer at %pr\n", res);
mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
drv->name); if (!mem) { /* * We cannot make this fatal. Sometimes this comes from magic * spaces our resource handlers simply don't know about. Use * the I/O-memory resource as-is and try to map that instead.
*/
drm_warn(dev, "could not acquire memory region %pr\n", res);
mem = res;
}
screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem)); if (!screen_base) return ERR_PTR(-ENOMEM);
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.