/* initialize bridge */ struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi) { struct drm_bridge *bridge = NULL; struct hdmi_bridge *hdmi_bridge; int ret; hdmi_bridge = devm_kzalloc(hdmi->dev->dev, sizeof(*hdmi_bridge), GFP_KERNEL); if (!hdmi_bridge) { ret = -ENOMEM; goto fail; } hdmi_bridge->hdmi = hdmi; bridge = &hdmi_bridge->base; bridge->funcs = &hdmi_bridge_funcs; ret = drm_bridge_attach(hdmi->dev, bridge); if (ret) goto fail; return bridge; fail: if (bridge) hdmi_bridge_destroy(bridge); return ERR_PTR(ret); }
/* initialize bridge */ struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi) { struct drm_bridge *bridge = NULL; struct hdmi_bridge *hdmi_bridge; int ret; hdmi_bridge = kzalloc(sizeof(*hdmi_bridge), GFP_KERNEL); if (!hdmi_bridge) { ret = -ENOMEM; goto fail; } hdmi_bridge->hdmi = hdmi_reference(hdmi); bridge = &hdmi_bridge->base; drm_bridge_init(hdmi->dev, bridge, &hdmi_bridge_funcs); return bridge; fail: if (bridge) hdmi_bridge_destroy(bridge); return ERR_PTR(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 hdmi_init() so that failure happens from * hdmi sub-device's probe. */ int hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev, struct drm_encoder *encoder) { struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = hdmi->pdev; int ret; hdmi->dev = dev; hdmi->encoder = encoder; hdmi_audio_infoframe_init(&hdmi->audio.infoframe); hdmi->bridge = hdmi_bridge_init(hdmi); if (IS_ERR(hdmi->bridge)) { ret = PTR_ERR(hdmi->bridge); dev_err(dev->dev, "failed to create HDMI bridge: %d\n", ret); hdmi->bridge = NULL; goto fail; } hdmi->connector = hdmi_connector_init(hdmi); if (IS_ERR(hdmi->connector)) { ret = PTR_ERR(hdmi->connector); dev_err(dev->dev, "failed to create HDMI connector: %d\n", ret); hdmi->connector = NULL; goto fail; } hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); if (hdmi->irq < 0) { ret = hdmi->irq; dev_err(dev->dev, "failed to get irq: %d\n", ret); goto fail; } ret = devm_request_irq(&pdev->dev, hdmi->irq, hdmi_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "hdmi_isr", hdmi); if (ret < 0) { dev_err(dev->dev, "failed to request IRQ%u: %d\n", hdmi->irq, ret); goto fail; } encoder->bridge = hdmi->bridge; priv->bridges[priv->num_bridges++] = hdmi->bridge; priv->connectors[priv->num_connectors++] = hdmi->connector; platform_set_drvdata(pdev, hdmi); return 0; fail: /* bridge is normally destroyed by drm: */ if (hdmi->bridge) { hdmi_bridge_destroy(hdmi->bridge); hdmi->bridge = NULL; } if (hdmi->connector) { hdmi->connector->funcs->destroy(hdmi->connector); hdmi->connector = NULL; } return ret; }