// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com>
*/
/* Process HPD: */
msm_hdmi_hpd_irq(hdmi->bridge);
/* Process DDC: */
msm_hdmi_i2c_irq(hdmi->i2c);
/* Process HDCP: */ if (hdmi->hdcp_ctrl)
msm_hdmi_hdcp_irq(hdmi->hdcp_ctrl);
/* TODO audio.. */
return IRQ_HANDLED;
}
staticvoid msm_hdmi_destroy(struct hdmi *hdmi)
{ /* * at this point, hpd has been disabled, * after flush workq, it's safe to deinit hdcp
*/ if (hdmi->workq)
destroy_workqueue(hdmi->workq);
msm_hdmi_hdcp_destroy(hdmi);
if (!phy_pdev) return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "phy driver is not ready\n");
hdmi->phy = platform_get_drvdata(phy_pdev); if (!hdmi->phy) {
put_device(&phy_pdev->dev); return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "phy driver is not ready\n");
}
hdmi->phy_dev = &phy_pdev->dev;
return 0;
}
/* construct hdmi at bind/probe time, grab all the resources. If * we are to EPROBE_DEFER we want to do it here, rather than later * at modeset_init() time
*/ staticint msm_hdmi_init(struct hdmi *hdmi)
{ struct platform_device *pdev = hdmi->pdev; int ret;
hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); if (!hdmi->workq) {
ret = -ENOMEM; goto fail;
}
hdmi->i2c = msm_hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) {
ret = PTR_ERR(hdmi->i2c);
DRM_DEV_ERROR(&pdev->dev, "failed to get i2c: %d\n", ret);
hdmi->i2c = NULL; goto fail;
}
hdmi->hdcp_ctrl = msm_hdmi_hdcp_init(hdmi); if (IS_ERR(hdmi->hdcp_ctrl)) {
dev_warn(&pdev->dev, "failed to init hdcp: disabled\n");
hdmi->hdcp_ctrl = NULL;
}
return 0;
fail:
msm_hdmi_destroy(hdmi);
return ret;
}
/* Second part of initialization, the drm/kms level modeset_init, * constructs/initializes mode objects, etc, is called from master * driver (not hdmi sub-device's probe/bind!) * * Any resource (regulator/clk/etc) which could be missing at boot * should be handled in msm_hdmi_init() so that failure happens from * hdmi sub-device's probe.
*/ int msm_hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev, struct drm_encoder *encoder)
{ int ret;
hdmi->dev = dev;
hdmi->encoder = encoder;
ret = msm_hdmi_bridge_init(hdmi); if (ret) {
DRM_DEV_ERROR(dev->dev, "failed to create HDMI bridge: %d\n", ret); goto fail;
}
if (hdmi->next_bridge) {
ret = drm_bridge_attach(hdmi->encoder, hdmi->next_bridge, hdmi->bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR); if (ret) {
DRM_DEV_ERROR(dev->dev, "failed to attach next HDMI bridge: %d\n", ret); goto fail;
}
}
hdmi->connector = drm_bridge_connector_init(hdmi->dev, encoder); if (IS_ERR(hdmi->connector)) {
ret = PTR_ERR(hdmi->connector);
DRM_DEV_ERROR(dev->dev, "failed to create HDMI connector: %d\n", ret);
hdmi->connector = NULL; goto fail;
}
hdmi->irq = platform_get_irq(pdev, 0); if (hdmi->irq < 0) return hdmi->irq;
hdmi->pwr_regs = devm_kcalloc(&pdev->dev,
config->pwr_reg_cnt, sizeof(hdmi->pwr_regs[0]),
GFP_KERNEL); if (!hdmi->pwr_regs) return -ENOMEM;
for (i = 0; i < config->pwr_reg_cnt; i++)
hdmi->pwr_regs[i].supply = config->pwr_reg_names[i];
ret = devm_regulator_bulk_get(&pdev->dev, config->pwr_reg_cnt, hdmi->pwr_regs); if (ret) return dev_err_probe(dev, ret, "failed to get pwr regulators\n");
hdmi->pwr_clks = devm_kcalloc(&pdev->dev,
config->pwr_clk_cnt, sizeof(hdmi->pwr_clks[0]),
GFP_KERNEL); if (!hdmi->pwr_clks) return -ENOMEM;
for (i = 0; i < config->pwr_clk_cnt; i++)
hdmi->pwr_clks[i].id = config->pwr_clk_names[i];
ret = devm_clk_bulk_get(&pdev->dev, config->pwr_clk_cnt, hdmi->pwr_clks); if (ret) return ret;
hdmi->extp_clk = devm_clk_get_optional(&pdev->dev, "extp"); if (IS_ERR(hdmi->extp_clk)) return dev_err_probe(dev, PTR_ERR(hdmi->extp_clk), "failed to get extp clock\n");
hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN); /* This will catch e.g. -EPROBE_DEFER */ if (IS_ERR(hdmi->hpd_gpiod)) return dev_err_probe(dev, PTR_ERR(hdmi->hpd_gpiod), "failed to get hpd gpio\n");
if (!hdmi->hpd_gpiod)
DBG("failed to get HPD gpio");
if (hdmi->hpd_gpiod)
gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD");
ret = msm_hdmi_get_phy(hdmi); if (ret) {
DRM_DEV_ERROR(&pdev->dev, "failed to get phy\n"); return ret;
}
ret = devm_pm_runtime_enable(&pdev->dev); if (ret) goto err_put_phy;
platform_set_drvdata(pdev, hdmi);
ret = component_add(&pdev->dev, &msm_hdmi_ops); if (ret) goto err_put_phy;
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.