Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}