/* initialize connector */ struct hdmi *hdmi_init(struct drm_device *dev, struct drm_encoder *encoder) { struct hdmi *hdmi = NULL; struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->hdmi_pdev; struct hdmi_platform_config *config; int i, ret; if (!pdev) { dev_err(dev->dev, "no hdmi device\n"); ret = -ENXIO; goto fail; } config = pdev->dev.platform_data; hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL); if (!hdmi) { ret = -ENOMEM; goto fail; } kref_init(&hdmi->refcount); hdmi->dev = dev; hdmi->pdev = pdev; hdmi->config = config; hdmi->encoder = encoder; /* not sure about which phy maps to which msm.. probably I miss some */ if (config->phy_init) hdmi->phy = config->phy_init(hdmi); else hdmi->phy = ERR_PTR(-ENXIO); if (IS_ERR(hdmi->phy)) { ret = PTR_ERR(hdmi->phy); dev_err(dev->dev, "failed to load phy: %d\n", ret); hdmi->phy = NULL; goto fail; } hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); if (IS_ERR(hdmi->mmio)) { ret = PTR_ERR(hdmi->mmio); goto fail; } BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs)); for (i = 0; i < config->hpd_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(dev->dev, "failed to get hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } hdmi->hpd_regs[i] = reg; } BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs)); for (i = 0; i < config->pwr_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(dev->dev, "failed to get pwr regulator: %s (%d)\n", config->pwr_reg_names[i], ret); goto fail; } hdmi->pwr_regs[i] = reg; } BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks)); for (i = 0; i < config->hpd_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(dev->dev, "failed to get hpd clk: %s (%d)\n", config->hpd_clk_names[i], ret); goto fail; } hdmi->hpd_clks[i] = clk; } BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks)); for (i = 0; i < config->pwr_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(dev->dev, "failed to get pwr clk: %s (%d)\n", config->pwr_clk_names[i], ret); goto fail; } hdmi->pwr_clks[i] = clk; } hdmi->i2c = hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); dev_err(dev->dev, "failed to get i2c: %d\n", ret); hdmi->i2c = NULL; goto fail; } 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; } if (!config->shared_irq) { hdmi->irq = platform_get_irq(pdev, 0); if (hdmi->irq < 0) { ret = hdmi->irq; dev_err(dev->dev, "failed to get irq: %d\n", ret); goto fail; } ret = devm_request_threaded_irq(&pdev->dev, hdmi->irq, NULL, 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; return hdmi; fail: if (hdmi) { /* bridge/connector are normally destroyed by drm: */ if (hdmi->bridge) hdmi->bridge->funcs->destroy(hdmi->bridge); if (hdmi->connector) hdmi->connector->funcs->destroy(hdmi->connector); hdmi_destroy(&hdmi->refcount); } return ERR_PTR(ret); }
/* 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 */ static struct hdmi *hdmi_init(struct platform_device *pdev) { struct hdmi_platform_config *config = pdev->dev.platform_data; struct hdmi *hdmi = NULL; int i, ret; hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) { ret = -ENOMEM; goto fail; } hdmi->pdev = pdev; hdmi->config = config; /* not sure about which phy maps to which msm.. probably I miss some */ if (config->phy_init) hdmi->phy = config->phy_init(hdmi); else hdmi->phy = ERR_PTR(-ENXIO); if (IS_ERR(hdmi->phy)) { ret = PTR_ERR(hdmi->phy); dev_err(&pdev->dev, "failed to load phy: %d\n", ret); hdmi->phy = NULL; goto fail; } hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); if (IS_ERR(hdmi->mmio)) { ret = PTR_ERR(hdmi->mmio); goto fail; } BUG_ON(config->hpd_reg_cnt > ARRAY_SIZE(hdmi->hpd_regs)); for (i = 0; i < config->hpd_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(&pdev->dev, "failed to get hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } hdmi->hpd_regs[i] = reg; } BUG_ON(config->pwr_reg_cnt > ARRAY_SIZE(hdmi->pwr_regs)); for (i = 0; i < config->pwr_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(&pdev->dev, "failed to get pwr regulator: %s (%d)\n", config->pwr_reg_names[i], ret); goto fail; } hdmi->pwr_regs[i] = reg; } BUG_ON(config->hpd_clk_cnt > ARRAY_SIZE(hdmi->hpd_clks)); for (i = 0; i < config->hpd_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get hpd clk: %s (%d)\n", config->hpd_clk_names[i], ret); goto fail; } hdmi->hpd_clks[i] = clk; } BUG_ON(config->pwr_clk_cnt > ARRAY_SIZE(hdmi->pwr_clks)); for (i = 0; i < config->pwr_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get pwr clk: %s (%d)\n", config->pwr_clk_names[i], ret); goto fail; } hdmi->pwr_clks[i] = clk; } hdmi->i2c = hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); dev_err(&pdev->dev, "failed to get i2c: %d\n", ret); hdmi->i2c = NULL; goto fail; } return hdmi; fail: if (hdmi) hdmi_destroy(hdmi); return ERR_PTR(ret); }
/* 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 */ static struct hdmi *hdmi_init(struct platform_device *pdev) { struct hdmi_platform_config *config = pdev->dev.platform_data; struct hdmi *hdmi = NULL; struct resource *res; int i, ret; hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) { ret = -ENOMEM; goto fail; } hdmi->pdev = pdev; hdmi->config = config; spin_lock_init(&hdmi->reg_lock); /* not sure about which phy maps to which msm.. probably I miss some */ if (config->phy_init) { hdmi->phy = config->phy_init(hdmi); if (IS_ERR(hdmi->phy)) { ret = PTR_ERR(hdmi->phy); dev_err(&pdev->dev, "failed to load phy: %d\n", ret); hdmi->phy = NULL; goto fail; } } hdmi->mmio = msm_ioremap(pdev, config->mmio_name, "HDMI"); if (IS_ERR(hdmi->mmio)) { ret = PTR_ERR(hdmi->mmio); goto fail; } /* HDCP needs physical address of hdmi register */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, config->mmio_name); hdmi->mmio_phy_addr = res->start; hdmi->qfprom_mmio = msm_ioremap(pdev, config->qfprom_mmio_name, "HDMI_QFPROM"); if (IS_ERR(hdmi->qfprom_mmio)) { dev_info(&pdev->dev, "can't find qfprom resource\n"); hdmi->qfprom_mmio = NULL; } hdmi->hpd_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_regs[0]) * config->hpd_reg_cnt, GFP_KERNEL); if (!hdmi->hpd_regs) { ret = -ENOMEM; goto fail; } for (i = 0; i < config->hpd_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->hpd_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(&pdev->dev, "failed to get hpd regulator: %s (%d)\n", config->hpd_reg_names[i], ret); goto fail; } hdmi->hpd_regs[i] = reg; } hdmi->pwr_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_regs[0]) * config->pwr_reg_cnt, GFP_KERNEL); if (!hdmi->pwr_regs) { ret = -ENOMEM; goto fail; } for (i = 0; i < config->pwr_reg_cnt; i++) { struct regulator *reg; reg = devm_regulator_get(&pdev->dev, config->pwr_reg_names[i]); if (IS_ERR(reg)) { ret = PTR_ERR(reg); dev_err(&pdev->dev, "failed to get pwr regulator: %s (%d)\n", config->pwr_reg_names[i], ret); goto fail; } hdmi->pwr_regs[i] = reg; } hdmi->hpd_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_clks[0]) * config->hpd_clk_cnt, GFP_KERNEL); if (!hdmi->hpd_clks) { ret = -ENOMEM; goto fail; } for (i = 0; i < config->hpd_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get hpd clk: %s (%d)\n", config->hpd_clk_names[i], ret); goto fail; } hdmi->hpd_clks[i] = clk; } hdmi->pwr_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_clks[0]) * config->pwr_clk_cnt, GFP_KERNEL); if (!hdmi->pwr_clks) { ret = -ENOMEM; goto fail; } for (i = 0; i < config->pwr_clk_cnt; i++) { struct clk *clk; clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get pwr clk: %s (%d)\n", config->pwr_clk_names[i], ret); goto fail; } hdmi->pwr_clks[i] = clk; } hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); hdmi->i2c = hdmi_i2c_init(hdmi); if (IS_ERR(hdmi->i2c)) { ret = PTR_ERR(hdmi->i2c); dev_err(&pdev->dev, "failed to get i2c: %d\n", ret); hdmi->i2c = NULL; goto fail; } hdmi->hdcp_ctrl = 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 hdmi; fail: if (hdmi) hdmi_destroy(hdmi); return ERR_PTR(ret); }