static int mxc_hdmi_core_probe(struct vmm_device *dev, const struct vmm_devtree_nodeid *nid) { struct mxc_hdmi_data *hdmi_data = NULL; unsigned long flags; virtual_addr_t base_va = 0L; int ret = VMM_EFAIL; hdmi_core_init = 0; hdmi_dma_running = 0; ret = vmm_devtree_request_regmap(dev->of_node, &base_va, 0, "MXC HDMI Core"); if (ret) { dev_err(dev, "failed to request regmap\n"); goto fail; } ret = hdmi_core_get_of_property(dev); if (ret < 0) { dev_err(dev, "get hdmi of property fail\n"); goto fail; } hdmi_data = vmm_devm_zalloc(dev, sizeof(struct mxc_hdmi_data)); if (!hdmi_data) { dev_err(dev, "Couldn't allocate mxc hdmi mfd device\n"); goto fail; } hdmi_data->dev = dev; pixel_clk = NULL; sample_rate = 48000; pixel_clk_rate = 0; hdmi_ratio = 100; spin_lock_init(&irq_spinlock); spin_lock_init(&edid_spinlock); spin_lock_init(&hdmi_cable_state_lock); spin_lock_init(&hdmi_blank_state_lock); spin_lock_init(&hdmi_audio_lock); spin_lock_irqsave(&hdmi_cable_state_lock, flags); hdmi_cable_state = 0; spin_unlock_irqrestore(&hdmi_cable_state_lock, flags); spin_lock_irqsave(&hdmi_blank_state_lock, flags); hdmi_blank_state = 0; spin_unlock_irqrestore(&hdmi_blank_state_lock, flags); spin_lock_irqsave(&hdmi_audio_lock, flags); #if 0 hdmi_audio_stream_playback = NULL; #endif hdmi_abort_state = 0; spin_unlock_irqrestore(&hdmi_audio_lock, flags); isfr_clk = devm_clk_get(dev, "hdmi_isfr"); if (IS_ERR(isfr_clk)) { ret = PTR_ERR(isfr_clk); dev_err(dev, "Unable to get HDMI isfr clk: %d\n", ret); goto fail; } ret = clk_prepare_enable(isfr_clk); if (ret < 0) { dev_err(dev, "Cannot enable HDMI clock: %d\n", ret); goto eclke; } pr_debug("%s isfr_clk:%lu\n", __func__, clk_get_rate(isfr_clk)); iahb_clk = devm_clk_get(dev, "hdmi_iahb"); if (IS_ERR(iahb_clk)) { ret = PTR_ERR(iahb_clk); dev_err(dev, "Unable to get HDMI iahb clk: %d\n", ret); goto eclkg2; } ret = clk_prepare_enable(iahb_clk); if (ret < 0) { dev_err(dev, "Cannot enable HDMI clock: %d\n", ret); goto eclke2; } hdmi_data->reg_base = (void *)base_va; hdmi_base = hdmi_data->reg_base; initialize_hdmi_ih_mutes(); /* Disable HDMI clocks until video/audio sub-drivers are initialized */ clk_disable_unprepare(isfr_clk); clk_disable_unprepare(iahb_clk); /* Replace platform data coming in with a local struct */ vmm_devdrv_set_data(dev, hdmi_data); return ret; eclke2: clk_put(iahb_clk); eclkg2: clk_disable_unprepare(isfr_clk); eclke: clk_put(isfr_clk); fail: if (hdmi_data) vmm_free(hdmi_data); return ret; }
static int imx_hdmi_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); const struct of_device_id *of_id = of_match_device(imx_hdmi_dt_ids, dev); struct drm_device *drm = data; struct device_node *np = dev->of_node; struct device_node *ddc_node; struct imx_hdmi *hdmi; struct resource *iores; int ret, irq; hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) return -ENOMEM; hdmi->dev = dev; hdmi->sample_rate = 48000; hdmi->ratio = 100; if (of_id) { const struct platform_device_id *device_id = of_id->data; hdmi->dev_type = device_id->driver_data; } ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); if (ddc_node) { hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); if (!hdmi->ddc) dev_dbg(hdmi->dev, "failed to read ddc node\n"); of_node_put(ddc_node); } else { dev_dbg(hdmi->dev, "no ddc property found\n"); } irq = platform_get_irq(pdev, 0); if (irq < 0) return -EINVAL; ret = devm_request_threaded_irq(dev, irq, imx_hdmi_hardirq, imx_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); if (ret) return ret; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); hdmi->regs = devm_ioremap_resource(dev, iores); if (IS_ERR(hdmi->regs)) return PTR_ERR(hdmi->regs); hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); if (IS_ERR(hdmi->regmap)) return PTR_ERR(hdmi->regmap); hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); if (IS_ERR(hdmi->isfr_clk)) { ret = PTR_ERR(hdmi->isfr_clk); dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret); return ret; } ret = clk_prepare_enable(hdmi->isfr_clk); if (ret) { dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret); return ret; } hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); if (IS_ERR(hdmi->iahb_clk)) { ret = PTR_ERR(hdmi->iahb_clk); dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret); goto err_isfr; } ret = clk_prepare_enable(hdmi->iahb_clk); if (ret) { dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret); goto err_isfr; } /* Product and revision IDs */ dev_info(dev, "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", hdmi_readb(hdmi, HDMI_DESIGN_ID), hdmi_readb(hdmi, HDMI_REVISION_ID), hdmi_readb(hdmi, HDMI_PRODUCT_ID0), hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); initialize_hdmi_ih_mutes(hdmi); /* * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator * N and cts values before enabling phy */ hdmi_init_clk_regenerator(hdmi); /* * Configure registers related to HDMI interrupt * generation before registering IRQ. */ hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0); /* Clear Hotplug interrupts */ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0); ret = imx_hdmi_fb_registered(hdmi); if (ret) goto err_iahb; ret = imx_hdmi_register(drm, hdmi); if (ret) goto err_iahb; /* Unmute interrupts */ hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0); dev_set_drvdata(dev, hdmi); return 0; err_iahb: clk_disable_unprepare(hdmi->iahb_clk); err_isfr: clk_disable_unprepare(hdmi->isfr_clk); return ret; }
static int mxc_hdmi_core_probe(struct platform_device *pdev) { struct fsl_mxc_hdmi_core_platform_data *pdata = pdev->dev.platform_data; struct mxc_hdmi_data *hdmi_data; struct resource *res; int ret = 0; #ifdef DEBUG overflow_lo = false; overflow_hi = false; #endif hdmi_core_init = 0; hdmi_dma_running = 0; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENOENT; hdmi_data = kzalloc(sizeof(struct mxc_hdmi_data), GFP_KERNEL); if (!hdmi_data) { dev_err(&pdev->dev, "Couldn't allocate mxc hdmi mfd device\n"); return -ENOMEM; } hdmi_data->pdev = pdev; pixel_clk = NULL; sample_rate = 48000; pixel_clk_rate = 0; hdmi_ratio = 100; irq_enable_cnt = 0; irq_initialized = false; irq_enabled = true; spin_lock_init(&irq_spinlock); spin_lock_init(&edid_spinlock); isfr_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_isfr_clk"); if (IS_ERR(isfr_clk)) { ret = PTR_ERR(isfr_clk); dev_err(&hdmi_data->pdev->dev, "Unable to get HDMI isfr clk: %d\n", ret); goto eclkg; } ret = clk_enable(isfr_clk); if (ret < 0) { dev_err(&pdev->dev, "Cannot enable HDMI clock: %d\n", ret); goto eclke; } pr_debug("%s isfr_clk:%d\n", __func__, (int)clk_get_rate(isfr_clk)); iahb_clk = clk_get(&hdmi_data->pdev->dev, "hdmi_iahb_clk"); if (IS_ERR(iahb_clk)) { ret = PTR_ERR(iahb_clk); dev_err(&hdmi_data->pdev->dev, "Unable to get HDMI iahb clk: %d\n", ret); goto eclkg2; } ret = clk_enable(iahb_clk); if (ret < 0) { dev_err(&pdev->dev, "Cannot enable HDMI clock: %d\n", ret); goto eclke2; } hdmi_data->reg_phys_base = res->start; if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { dev_err(&pdev->dev, "request_mem_region failed\n"); ret = -EBUSY; goto emem; } hdmi_data->reg_base = ioremap(res->start, resource_size(res)); if (!hdmi_data->reg_base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; goto eirq; } hdmi_base = (unsigned long)hdmi_data->reg_base; pr_debug("\n%s hdmi hw base = 0x%08x\n\n", __func__, (int)res->start); mxc_hdmi_ipu_id = pdata->ipu_id; mxc_hdmi_disp_id = pdata->disp_id; initialize_hdmi_ih_mutes(); /* Disable HDMI clocks until video/audio sub-drivers are initialized */ clk_disable(isfr_clk); clk_disable(iahb_clk); /* Replace platform data coming in with a local struct */ platform_set_drvdata(pdev, hdmi_data); return ret; eirq: release_mem_region(res->start, resource_size(res)); emem: clk_disable(iahb_clk); eclke2: clk_put(iahb_clk); eclkg2: clk_disable(isfr_clk); eclke: clk_put(isfr_clk); eclkg: kfree(hdmi_data); return ret; }
int dw_hdmi_bind(struct device *dev, struct device *master, void *data, struct drm_encoder *encoder, struct resource *iores, int irq, const struct dw_hdmi_plat_data *plat_data) { struct drm_device *drm = data; struct device_node *np = dev->of_node; struct device_node *ddc_node; struct dw_hdmi *hdmi; int ret; u32 val = 1; hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) return -ENOMEM; hdmi->plat_data = plat_data; hdmi->dev = dev; hdmi->dev_type = plat_data->dev_type; hdmi->sample_rate = 48000; hdmi->ratio = 100; hdmi->encoder = encoder; mutex_init(&hdmi->audio_mutex); of_property_read_u32(np, "reg-io-width", &val); switch (val) { case 4: hdmi->write = dw_hdmi_writel; hdmi->read = dw_hdmi_readl; break; case 1: hdmi->write = dw_hdmi_writeb; hdmi->read = dw_hdmi_readb; break; default: dev_err(dev, "reg-io-width must be 1 or 4\n"); return -EINVAL; } ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); if (ddc_node) { hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); of_node_put(ddc_node); if (!hdmi->ddc) { dev_dbg(hdmi->dev, "failed to read ddc node\n"); return -EPROBE_DEFER; } } else { dev_dbg(hdmi->dev, "no ddc property found\n"); } hdmi->regs = devm_ioremap_resource(dev, iores); if (IS_ERR(hdmi->regs)) return PTR_ERR(hdmi->regs); hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr"); if (IS_ERR(hdmi->isfr_clk)) { ret = PTR_ERR(hdmi->isfr_clk); dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret); return ret; } ret = clk_prepare_enable(hdmi->isfr_clk); if (ret) { dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret); return ret; } hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb"); if (IS_ERR(hdmi->iahb_clk)) { ret = PTR_ERR(hdmi->iahb_clk); dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret); goto err_isfr; } ret = clk_prepare_enable(hdmi->iahb_clk); if (ret) { dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret); goto err_isfr; } /* Product and revision IDs */ dev_info(dev, "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n", hdmi_readb(hdmi, HDMI_DESIGN_ID), hdmi_readb(hdmi, HDMI_REVISION_ID), hdmi_readb(hdmi, HDMI_PRODUCT_ID0), hdmi_readb(hdmi, HDMI_PRODUCT_ID1)); initialize_hdmi_ih_mutes(hdmi); ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq, dw_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); if (ret) goto err_iahb; /* * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator * N and cts values before enabling phy */ hdmi_init_clk_regenerator(hdmi); /* * Configure registers related to HDMI interrupt * generation before registering IRQ. */ hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0); /* Clear Hotplug interrupts */ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0); ret = dw_hdmi_fb_registered(hdmi); if (ret) goto err_iahb; ret = dw_hdmi_register(drm, hdmi); if (ret) goto err_iahb; /* Unmute interrupts */ hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0); dev_set_drvdata(dev, hdmi); return 0; err_iahb: clk_disable_unprepare(hdmi->iahb_clk); err_isfr: clk_disable_unprepare(hdmi->isfr_clk); return ret; }